Bug Summary

File:root/firefox-clang/dom/events/EventStateManager.cpp
Warning:line 5376, 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/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -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-09-01-224014-2642839-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/UIEvent.h"
76#include "mozilla/dom/UIEventBinding.h"
77#include "mozilla/dom/UserActivation.h"
78#include "mozilla/dom/WheelEventBinding.h"
79#include "mozilla/glean/ProcesstoolsMetrics.h"
80#include "nsCOMPtr.h"
81#include "nsComboboxControlFrame.h"
82#include "nsCommandParams.h"
83#include "nsContentAreaDragDrop.h"
84#include "nsContentUtils.h"
85#include "nsCopySupport.h"
86#include "nsFocusManager.h"
87#include "nsFontMetrics.h"
88#include "nsFrameLoaderOwner.h"
89#include "nsFrameManager.h"
90#include "nsFrameSelection.h"
91#include "nsGenericHTMLElement.h"
92#include "nsGkAtoms.h"
93#include "nsIBaseWindow.h"
94#include "nsIBrowserChild.h"
95#include "nsIClipboard.h"
96#include "nsIContent.h"
97#include "nsIContentInlines.h"
98#include "nsIController.h"
99#include "nsICookieJarSettings.h"
100#include "nsIDOMXULControlElement.h"
101#include "nsIDocShell.h"
102#include "nsIDocumentViewer.h"
103#include "nsIDragService.h"
104#include "nsIDragSession.h"
105#include "nsIFormControl.h"
106#include "nsIFrame.h"
107#include "nsIInterfaceRequestorUtils.h"
108#include "nsIObserverService.h"
109#include "nsIProperties.h"
110#include "nsISupportsPrimitives.h"
111#include "nsITimer.h"
112#include "nsIWeakReferenceUtils.h"
113#include "nsIWebNavigation.h"
114#include "nsIWidget.h"
115#include "nsLayoutUtils.h"
116#include "nsLiteralString.h"
117#include "nsMenuPopupFrame.h"
118#include "nsNameSpaceManager.h"
119#include "nsPIDOMWindow.h"
120#include "nsPIWindowRoot.h"
121#include "nsPresContext.h"
122#include "nsServiceManagerUtils.h"
123#include "nsSubDocumentFrame.h"
124#include "nsTArray.h"
125#include "nsTreeBodyFrame.h"
126#include "nsUnicharUtils.h"
127
128#ifdef XP_MACOSX
129# import <ApplicationServices/ApplicationServices.h>
130#endif
131
132namespace mozilla {
133
134using namespace dom;
135
136// Log the mouse cursor updates. That should be updated only by the events for
137// the last pointer which is actually handled as a user input. I.e., should not
138// be updated by synthesized mouse/pointer move events which are not for the
139// last pointer.
140// - MouseCursorUpdate:3 logs only when EventStateManager and BrowserParent
141// updated the cursor.
142// - MouseCursorUpdate:4 logs any results when BrowserParent handles that.
143// - MouseCursorUpdate:5 logs when UpdateCursor() stopped updating the cursor.
144//
145// NOTE: This can work only on debug builds for avoiding to the damage to the
146// performance.
147LazyLogModule gMouseCursorUpdates("MouseCursorUpdates");
148
149static const LayoutDeviceIntPoint kInvalidRefPoint =
150 LayoutDeviceIntPoint(-1, -1);
151
152static uint32_t gMouseOrKeyboardEventCounter = 0;
153// Like gMouseOrKeyboardEventCounter, but excludes synthesized mouse/pointer
154// events (e.g. synthesized pointer moves dispatched when content shifts under a
155// stationary cursor). Drives the "non-synthesized" active-tick notifications so
156// telemetry can record a corrected active tick alongside the legacy one.
157static uint32_t gNonSynthesizedMouseOrKeyboardEventCounter = 0;
158static nsITimer* gUserInteractionTimer = nullptr;
159static nsITimerCallback* gUserInteractionTimerCallback = nullptr;
160
161static const double kCursorLoadingTimeout = 1000; // ms
162constinit static AutoWeakFrame gLastCursorSourceFrame;
163static TimeStamp gLastCursorUpdateTime;
164static TimeStamp gTypingStartTime;
165static TimeStamp gTypingEndTime;
166static int32_t gTypingInteractionKeyPresses = 0;
167constinit static dom::InteractionData gTypingInteraction = {};
168
169static inline int32_t RoundDown(double aDouble) {
170 return (aDouble > 0) ? static_cast<int32_t>(floor(aDouble))
171 : static_cast<int32_t>(ceil(aDouble));
172}
173
174static bool IsSelectingLink(nsIFrame* aTargetFrame) {
175 if (!aTargetFrame) {
176 return false;
177 }
178 const nsFrameSelection* frameSel = aTargetFrame->GetConstFrameSelection();
179 if (!frameSel || !frameSel->GetDragState()) {
180 return false;
181 }
182
183 if (!nsContentUtils::GetClosestLinkInFlatTree(aTargetFrame->GetContent())) {
184 return false;
185 }
186 return true;
187}
188
189static UniquePtr<WidgetMouseEvent> CreateMouseOrPointerWidgetEvent(
190 const WidgetMouseEvent* aMouseEvent, EventMessage aMessage,
191 EventTarget* aRelatedTarget);
192
193/**
194 * Returns the common ancestor for mouseup purpose, given the
195 * current mouseup target and the previous mousedown target.
196 */
197static nsINode* GetCommonAncestorForMouseUp(
198 nsINode* aCurrentMouseUpTarget, nsINode* aLastMouseDownTarget,
199 const Maybe<FormControlType>& aLastMouseDownInputControlType) {
200 if (!aCurrentMouseUpTarget || !aLastMouseDownTarget) {
201 return nullptr;
202 }
203
204 if (aCurrentMouseUpTarget == aLastMouseDownTarget) {
205 return aCurrentMouseUpTarget;
206 }
207
208 // Build the chain of parents
209 AutoTArray<nsINode*, 30> parents1;
210 do {
211 parents1.AppendElement(aCurrentMouseUpTarget);
212 aCurrentMouseUpTarget = aCurrentMouseUpTarget->GetFlattenedTreeParentNode();
213 } while (aCurrentMouseUpTarget);
214
215 AutoTArray<nsINode*, 30> parents2;
216 do {
217 parents2.AppendElement(aLastMouseDownTarget);
218 if (aLastMouseDownTarget == parents1.LastElement()) {
219 break;
220 }
221 aLastMouseDownTarget = aLastMouseDownTarget->GetFlattenedTreeParentNode();
222 } while (aLastMouseDownTarget);
223
224 // Find where the parent chain differs
225 uint32_t pos1 = parents1.Length();
226 uint32_t pos2 = parents2.Length();
227 nsINode* parent = nullptr;
228 for (uint32_t len = std::min(pos1, pos2); len > 0; --len) {
229 nsINode* child1 = parents1.ElementAt(--pos1);
230 nsINode* child2 = parents2.ElementAt(--pos2);
231 if (child1 != child2) {
232 break;
233 }
234
235 // If the input control type is different between mouseup and mousedown,
236 // this is not a valid click.
237 if (HTMLInputElement* input = HTMLInputElement::FromNodeOrNull(child1)) {
238 if (aLastMouseDownInputControlType.isSome() &&
239 aLastMouseDownInputControlType.ref() != input->ControlType()) {
240 break;
241 }
242 }
243 parent = child1;
244 }
245
246 return parent;
247}
248
249static bool HasNativeKeyBindings(nsIContent* aContent,
250 WidgetKeyboardEvent* aEvent) {
251 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"
, 251); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyPress"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
252
253 if (!aContent) {
254 return false;
255 }
256
257 const RefPtr<dom::Element> targetElement = aContent->AsElement();
258 if (!targetElement) {
259 return false;
260 }
261
262 const auto type = [&]() -> Maybe<NativeKeyBindingsType> {
263 if (BrowserParent::GetFrom(targetElement)) {
264 const nsCOMPtr<nsIWidget> widget = aEvent->mWidget;
265 if (MOZ_UNLIKELY(!widget)(__builtin_expect(!!(!widget), 0))) {
266 return Nothing();
267 }
268 widget::InputContext context = widget->GetInputContext();
269 return context.mIMEState.IsEditable()
270 ? Some(context.GetNativeKeyBindingsType())
271 : Nothing();
272 }
273
274 const auto* const textControlElement =
275 TextControlElement::FromNode(targetElement);
276 if (textControlElement &&
277 textControlElement->IsSingleLineTextControlOrTextArea() &&
278 !textControlElement->IsInDesignMode()) {
279 return textControlElement->IsTextArea()
280 ? Some(NativeKeyBindingsType::MultiLineEditor)
281 : Some(NativeKeyBindingsType::SingleLineEditor);
282 }
283 return targetElement->IsEditable()
284 ? Some(NativeKeyBindingsType::RichTextEditor)
285 : Nothing();
286 }();
287 if (type.isNothing()) {
288 return false;
289 }
290
291 const nsTArray<CommandInt>& commands =
292 aEvent->EditCommandsConstRef(type.value());
293 return !commands.IsEmpty();
294}
295
296LazyLogModule sMouseBoundaryLog("MouseBoundaryEvents");
297LazyLogModule sPointerBoundaryLog("PointerBoundaryEvents");
298
299/******************************************************************/
300/* mozilla::UITimerCallback */
301/******************************************************************/
302
303class UITimerCallback final : public nsITimerCallback, public nsINamed {
304 public:
305 UITimerCallback() : mPreviousCount(0), mPreviousNonSynthesizedCount(0) {}
306 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:
307 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"
); }
308 NS_DECL_NSINAMEDvirtual nsresult GetName(nsACString& aName) override;
309 private:
310 ~UITimerCallback() = default;
311 uint32_t mPreviousCount;
312 uint32_t mPreviousNonSynthesizedCount;
313};
314
315NS_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"
, 315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 315
); __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", 315
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"UITimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 315); __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"
, 315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 315
); __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", 315
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"UITimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 315); __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", 315
); 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; }
316
317// If aTimer is nullptr, this method always sends "user-interaction-inactive"
318// notification.
319NS_IMETHODIMPnsresult
320UITimerCallback::Notify(nsITimer* aTimer) {
321 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
322 // ObserverService shutdown happens after XPCOMShutdownThreads.
323 if (!obs || AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdownThreads)) {
324 return NS_ERROR_FAILURE;
325 }
326 if ((gMouseOrKeyboardEventCounter == mPreviousCount) || !aTimer) {
327 gMouseOrKeyboardEventCounter = 0;
328 gNonSynthesizedMouseOrKeyboardEventCounter = 0;
329 obs->NotifyObservers(nullptr, "user-interaction-inactive", nullptr);
330 obs->NotifyObservers(nullptr, "user-interaction-inactive-non-synthesized",
331 nullptr);
332 if (gUserInteractionTimer) {
333 gUserInteractionTimer->Cancel();
334 NS_RELEASE(gUserInteractionTimer)do { (gUserInteractionTimer)->Release(); (gUserInteractionTimer
) = 0; } while (0)
;
335 }
336 } else {
337 obs->NotifyObservers(nullptr, "user-interaction-active", nullptr);
338 // The corrected active tick only stays active while non-synthesized events
339 // keep arriving, even if synthesized events alone kept the legacy tick
340 // active during this interval.
341 if (gNonSynthesizedMouseOrKeyboardEventCounter ==
342 mPreviousNonSynthesizedCount) {
343 obs->NotifyObservers(nullptr, "user-interaction-inactive-non-synthesized",
344 nullptr);
345 } else {
346 obs->NotifyObservers(nullptr, "user-interaction-active-non-synthesized",
347 nullptr);
348 }
349 EventStateManager::UpdateUserActivityTimer();
350
351 if (XRE_IsParentProcess()) {
352 hal::BatteryInformation batteryInfo;
353 hal::GetCurrentBatteryInformation(&batteryInfo);
354 glean::power_battery::percentage_when_user_active.AccumulateSingleSample(
355 uint64_t(batteryInfo.level() * 100));
356 }
357 }
358 mPreviousCount = gMouseOrKeyboardEventCounter;
359 mPreviousNonSynthesizedCount = gNonSynthesizedMouseOrKeyboardEventCounter;
360 return NS_OK;
361}
362
363NS_IMETHODIMPnsresult
364UITimerCallback::GetName(nsACString& aName) {
365 aName.AssignLiteral("UITimerCallback_timer");
366 return NS_OK;
367}
368
369/******************************************************************/
370/* mozilla::OverOutElementsWrapper */
371/******************************************************************/
372
373NS_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; }
374 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; }
375 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; }
376NS_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"
, 376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 376
); __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; }
377NS_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"
, 377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 377
); __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); }
378
379NS_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"
, 379); 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
380 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
381NS_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"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 381); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
382
383already_AddRefed<nsIWidget> OverOutElementsWrapper::GetLastOverWidget() const {
384 nsCOMPtr<nsIWidget> widget = do_QueryReferent(mLastOverWidget);
385 return widget.forget();
386}
387
388void OverOutElementsWrapper::ContentRemoved(nsIContent& aContent) {
389 if (!mDeepestEnterEventTarget) {
390 return;
391 }
392
393 if (!nsContentUtils::ContentIsFlattenedTreeDescendantOf(
394 mDeepestEnterEventTarget, &aContent)) {
395 return;
396 }
397
398 LogModule* const logModule = mType == BoundaryEventType::Mouse
399 ? sMouseBoundaryLog
400 : sPointerBoundaryLog;
401
402 if (mDispatchingOverEventTarget &&
403 (mDeepestEnterEventTarget == mDispatchingOverEventTarget ||
404 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
405 mDispatchingOverEventTarget, &aContent))) {
406 if (mDispatchingOverEventTarget ==
407 mDispatchingOutOrDeepestLeaveEventTarget) {
408 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)
409 ("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)
410 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)
411 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)
;
412 mDispatchingOutOrDeepestLeaveEventTarget = nullptr;
413 }
414 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)
415 ("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)
416 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)
;
417 mDispatchingOverEventTarget = nullptr;
418 }
419 if (mDispatchingOutOrDeepestLeaveEventTarget &&
420 (mDeepestEnterEventTarget == mDispatchingOutOrDeepestLeaveEventTarget ||
421 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
422 mDispatchingOutOrDeepestLeaveEventTarget, &aContent))) {
423 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)
424 ("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)
425 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)
426 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)
;
427 mDispatchingOutOrDeepestLeaveEventTarget = nullptr;
428 }
429 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)
430 ("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)
431 "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)
432 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)
433 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)
434 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)
435 ? 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)
436 : "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)
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 UpdateDeepestEnterEventTarget(aContent.GetFlattenedTreeParent());
439}
440
441void OverOutElementsWrapper::TryToRestorePendingRemovedOverTarget(
442 const WidgetEvent* aEvent) {
443 if (!MaybeHasPendingRemovingOverEventTarget()) {
444 return;
445 }
446
447 LogModule* const logModule = mType == BoundaryEventType::Mouse
448 ? sMouseBoundaryLog
449 : sPointerBoundaryLog;
450
451 // If we receive a mouse event immediately, let's try to restore the last
452 // "over" event target as the following "out" event target. We assume that a
453 // synthesized mousemove or another mouse event is being dispatched at latest
454 // the next animation frame from the removal. However, synthesized mouse move
455 // which is enqueued by ContentRemoved() may not sent to this instance because
456 // the target is considered with the latest layout, so the document of this
457 // instance may be moved somewhere before the next animation frame.
458 // Therefore, we should not restore the last "over" target if we receive an
459 // unexpected event like a keyboard event, a wheel event, etc.
460 if (aEvent->AsMouseEvent()) {
461 // Restore the original "over" event target should be allowed only when it's
462 // reconnected under the last deepest "enter" event target because we need
463 // to dispatch "leave" events later at least on the ancestors which have
464 // never been removed from the tree.
465 // XXX If new ancestor is inserted between mDeepestEnterEventTarget and
466 // mPendingToRemoveLastOverEventTarget, we will dispatch "leave" event even
467 // though we have not dispatched "enter" event on the element. For fixing
468 // this, we need to store the full path of the last "out" event target when
469 // it's removed from the tree. I guess we can be relax for this issue
470 // because this hack is required for web apps which reconnect the target
471 // to the same position immediately.
472 // XXX Should be IsInclusiveFlatTreeDescendantOf()? However, it may
473 // be reconnected into a subtree which is different from where the
474 // last over element was.
475 nsCOMPtr<nsIContent> pendingRemovingOverEventTarget =
476 GetPendingRemovingOverEventTarget();
477 if (pendingRemovingOverEventTarget &&
478 pendingRemovingOverEventTarget->IsInclusiveDescendantOf(
479 mDeepestEnterEventTarget)) {
480 // StoreOverEventTargetAndDeepestEnterEventTarget() always resets
481 // mLastOverWidget. When we restore the pending removing "over" event
482 // target, we need to keep storing the original "over" widget too.
483 nsCOMPtr<nsIWeakReference> widget = std::move(mLastOverWidget);
484 StoreOverEventTargetAndDeepestEnterEventTarget(
485 pendingRemovingOverEventTarget);
486 mLastOverWidget = std::move(widget);
487 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)
488 ("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)
489 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)
;
490 return;
491 }
492 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)
493 ("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)
494 "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)
495 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)
496 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)
;
497 } else {
498 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)
499 ("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)
500 "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)
501 "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)
502 "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)
503 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)
;
504 }
505
506 // Now, we should not restore mPendingRemovingOverEventTarget to
507 // mDeepestEnterEventTarget anymore since mPendingRemovingOverEventTarget was
508 // moved outside the subtree of mDeepestEnterEventTarget.
509 mPendingRemovingOverEventTarget = nullptr;
510}
511
512void OverOutElementsWrapper::WillDispatchOverAndEnterEvent(
513 nsIContent* aOverEventTarget) {
514 StoreOverEventTargetAndDeepestEnterEventTarget(aOverEventTarget);
515 // Store the first "over" event target we fire and don't refire "over" event
516 // to that element while the first "over" event is still ongoing.
517 mDispatchingOverEventTarget = aOverEventTarget;
518}
519
520void OverOutElementsWrapper::DidDispatchOverAndEnterEvent(
521 nsIContent* aOriginalOverTargetInComposedDoc,
522 nsIWidget* aOverEventTargetWidget) {
523 mDispatchingOverEventTarget = nullptr;
524 mLastOverWidget = do_GetWeakReference(aOverEventTargetWidget);
525
526 // Pointer Events define that once the `pointerover` event target is removed
527 // from the tree, `pointerout` should not be fired on that and the closest
528 // connected ancestor at the target removal should be kept as the deepest
529 // `pointerleave` target. Therefore, we don't need the special handling for
530 // `pointerout` event target if the last `pointerover` target is temporarily
531 // removed from the tree.
532 if (mType == OverOutElementsWrapper::BoundaryEventType::Pointer) {
533 return;
534 }
535
536 // Assume that the caller checks whether aOriginalOverTarget is in the
537 // original document. If we don't enable the strict mouse/pointer event
538 // boundary event dispatching by the pref (see below),
539 // mDeepestEnterEventTarget is set to nullptr when the last "over" target is
540 // removed. Therefore, we cannot check whether aOriginalOverTarget is in the
541 // original document here.
542 if (!aOriginalOverTargetInComposedDoc) {
543 return;
544 }
545 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", 547
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget->GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc()"
")"); do { MOZ_CrashSequence(__null, 547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
546 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", 547
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget->GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc()"
")"); do { MOZ_CrashSequence(__null, 547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
547 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", 547
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget->GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc()"
")"); do { MOZ_CrashSequence(__null, 547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
548 // If the "mouseover" event target is removed temporarily while we're
549 // dispatching "mouseover" and "mouseenter" events and the target gets back
550 // under the deepest enter event target, we should restore the "mouseover"
551 // target.
552 if (!LastOverEventTargetIsOutEventTarget() && mDeepestEnterEventTarget &&
553 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
554 aOriginalOverTargetInComposedDoc, mDeepestEnterEventTarget)) {
555 StoreOverEventTargetAndDeepestEnterEventTarget(
556 aOriginalOverTargetInComposedDoc);
557 LogModule* const logModule = mType == BoundaryEventType::Mouse
558 ? sMouseBoundaryLog
559 : sPointerBoundaryLog;
560 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)
561 ("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)
562 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)
;
563 }
564}
565
566void OverOutElementsWrapper::StoreOverEventTargetAndDeepestEnterEventTarget(
567 nsIContent* aOverEventTargetAndDeepestEnterEventTarget) {
568 mDeepestEnterEventTarget = aOverEventTargetAndDeepestEnterEventTarget;
569 mPendingRemovingOverEventTarget = nullptr;
570 mDeepestEnterEventTargetIsOverEventTarget = !!mDeepestEnterEventTarget;
571 mLastOverWidget = nullptr; // Set it after dispatching the "over" event.
572}
573
574void OverOutElementsWrapper::UpdateDeepestEnterEventTarget(
575 nsIContent* aDeepestEnterEventTarget) {
576 if (MOZ_UNLIKELY(mDeepestEnterEventTarget == aDeepestEnterEventTarget)(__builtin_expect(!!(mDeepestEnterEventTarget == aDeepestEnterEventTarget
), 0))
) {
577 return;
578 }
579
580 if (!aDeepestEnterEventTarget) {
581 // If the root element is removed, we don't need to dispatch "leave"
582 // events on any elements. Therefore, we can forget everything.
583 StoreOverEventTargetAndDeepestEnterEventTarget(nullptr);
584 return;
585 }
586
587 if (LastOverEventTargetIsOutEventTarget()) {
588 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", 588
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget"
")"); do { MOZ_CrashSequence(__null, 588); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
589 if (mType == BoundaryEventType::Pointer) {
590 // The spec of Pointer Events defines that once the `pointerover` event
591 // target is removed from the tree, `pointerout` should not be fired on
592 // that and the closest connected ancestor at the target removal should be
593 // kept as the deepest `pointerleave` target. All browsers considers the
594 // last `pointerover` event target is removed immediately when it occurs.
595 // Therefore, we don't need the special handling which we do for the
596 // `mouseout` event target below for considering whether we'll dispatch
597 // `pointerout` on the last `pointerover` target.
598 mPendingRemovingOverEventTarget = nullptr;
599 } else if (
600 !StaticPrefs::
601 dom_event_mouse_boundary_restore_last_over_target_from_temporary_removal()) {
602 // The spec of UI Events do not define that browsers should keep storing
603 // the last `mouseover` target when it's removed temporarily and
604 // reconnected immediately. We've decided to follow Chrome's behavior for
605 // now. However, there is a pref to bring back the old behavior if
606 // needed.
607 mPendingRemovingOverEventTarget = nullptr;
608 } else {
609 // However, Safari and old Chrome restore the last `mouseover` target when
610 // it's temporarily removed and reconnected immediately. Therefore, we
611 // should follow them by default. However, we should keep the old
612 // behavior for making it easier to backout the new behavior with
613 // disabling the pref.
614 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"
, 614); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPendingRemovingOverEventTarget"
")"); do { MOZ_CrashSequence(__null, 614); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
615 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", 615
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget"
")"); do { MOZ_CrashSequence(__null, 615); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
616 mPendingRemovingOverEventTarget =
617 do_GetWeakReference(mDeepestEnterEventTarget);
618 }
619 } else {
620 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", 620
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDeepestEnterEventTargetIsOverEventTarget"
")"); do { MOZ_CrashSequence(__null, 620); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
621 // If mDeepestEnterEventTarget is not the last "over" event target, we've
622 // already done the complicated state managing above. Therefore, we only
623 // need to update mDeepestEnterEventTarget in this case.
624 }
625 mDeepestEnterEventTarget = aDeepestEnterEventTarget;
626 mDeepestEnterEventTargetIsOverEventTarget = false;
627 // Do not update mLastOverWidget here because it's required to ignore some
628 // following pointer events which are fired on widget under different top
629 // level widget.
630}
631
632/******************************************************************/
633/* mozilla::EventStateManager */
634/******************************************************************/
635
636static uint32_t sESMInstanceCount = 0;
637
638bool EventStateManager::sNormalLMouseEventInProcess = false;
639int16_t EventStateManager::sCurrentMouseBtn = MouseButton::eNotPressed;
640EventStateManager* EventStateManager::sActiveESM = nullptr;
641EventStateManager* EventStateManager::sCursorSettingManager = nullptr;
642constinit AutoWeakFrame EventStateManager::sLastDragOverFrame{};
643LayoutDeviceIntPoint EventStateManager::sPreLockScreenPoint = kInvalidRefPoint;
644LayoutDeviceIntPoint EventStateManager::sLastRefPoint = kInvalidRefPoint;
645LayoutDeviceIntPoint EventStateManager::sLastRefPointOfRawUpdate =
646 kInvalidRefPoint;
647CSSIntPoint EventStateManager::sLastScreenPoint = CSSIntPoint(0, 0);
648LayoutDeviceIntPoint EventStateManager::sSynthCenteringPoint = kInvalidRefPoint;
649CSSIntPoint EventStateManager::sLastClientPoint = CSSIntPoint(0, 0);
650constinit nsCOMPtr<nsIContent> EventStateManager::sDragOverContent;
651
652EventStateManager::WheelPrefs* EventStateManager::WheelPrefs::sInstance =
653 nullptr;
654EventStateManager::DeltaAccumulator*
655 EventStateManager::DeltaAccumulator::sInstance = nullptr;
656
657constexpr const StyleCursorKind kInvalidCursorKind =
658 static_cast<StyleCursorKind>(255);
659
660EventStateManager::EventStateManager()
661 : mLockCursor(kInvalidCursorKind),
662 mCurrentTarget(nullptr),
663 // init d&d gesture state machine variables
664 mGestureDownPoint(0, 0),
665 mGestureModifiers(0),
666 mGestureDownButtons(0),
667 mGestureDownButton(0),
668 mPresContext(nullptr),
669 mShouldAlwaysUseLineDeltas(false),
670 mShouldAlwaysUseLineDeltasInitialized(false),
671 mInTouchDrag(false),
672 m_haveShutdown(false) {
673 if (sESMInstanceCount == 0) {
674 gUserInteractionTimerCallback = new UITimerCallback();
675 if (gUserInteractionTimerCallback) NS_ADDREF(gUserInteractionTimerCallback)(gUserInteractionTimerCallback)->AddRef();
676 UpdateUserActivityTimer();
677 }
678 ++sESMInstanceCount;
679}
680
681// static
682LazyLogModule& EventStateManager::MouseCursorUpdateLogRef() {
683 return gMouseCursorUpdates;
684}
685
686nsresult EventStateManager::UpdateUserActivityTimer() {
687 if (!gUserInteractionTimerCallback) return NS_OK;
688
689 if (!gUserInteractionTimer) {
690 gUserInteractionTimer = NS_NewTimer().take();
691 }
692
693 if (gUserInteractionTimer) {
694 gUserInteractionTimer->InitWithCallback(
695 gUserInteractionTimerCallback,
696 StaticPrefs::dom_events_user_interaction_interval(),
697 nsITimer::TYPE_ONE_SHOT);
698 }
699 return NS_OK;
700}
701
702void EventStateManager::Init() {
703 nsCOMPtr<nsIObserverService> observerService =
704 mozilla::services::GetObserverService();
705 if (observerService) {
706 observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown", true);
707 }
708}
709
710bool EventStateManager::ShouldAlwaysUseLineDeltas() {
711 if (MOZ_UNLIKELY(!mShouldAlwaysUseLineDeltasInitialized)(__builtin_expect(!!(!mShouldAlwaysUseLineDeltasInitialized),
0))
) {
712 mShouldAlwaysUseLineDeltasInitialized = true;
713 mShouldAlwaysUseLineDeltas =
714 !StaticPrefs::dom_event_wheel_deltaMode_lines_disabled();
715 if (!mShouldAlwaysUseLineDeltas && mDocument) {
716 if (nsIPrincipal* principal =
717 mDocument->GetPrincipalForPrefBasedHacks()) {
718 mShouldAlwaysUseLineDeltas = principal->IsURIInPrefList(
719 "dom.event.wheel-deltaMode-lines.always-enabled");
720 }
721 }
722 }
723 return mShouldAlwaysUseLineDeltas;
724}
725
726EventStateManager::~EventStateManager() {
727 ReleaseCurrentIMEContentObserver();
728
729 if (sActiveESM == this) {
730 sActiveESM = nullptr;
731 }
732
733 if (StaticPrefs::ui_click_hold_context_menus()) {
734 KillClickHoldTimer();
735 }
736
737 if (sCursorSettingManager == this) {
738 sCursorSettingManager = nullptr;
739 }
740
741 --sESMInstanceCount;
742 if (sESMInstanceCount == 0) {
743 WheelTransaction::Shutdown();
744 if (gUserInteractionTimerCallback) {
745 gUserInteractionTimerCallback->Notify(nullptr);
746 NS_RELEASE(gUserInteractionTimerCallback)do { (gUserInteractionTimerCallback)->Release(); (gUserInteractionTimerCallback
) = 0; } while (0)
;
747 }
748 if (gUserInteractionTimer) {
749 gUserInteractionTimer->Cancel();
750 NS_RELEASE(gUserInteractionTimer)do { (gUserInteractionTimer)->Release(); (gUserInteractionTimer
) = 0; } while (0)
;
751 }
752 WheelPrefs::Shutdown();
753 DeltaAccumulator::Shutdown();
754 }
755
756 if (sDragOverContent && sDragOverContent->OwnerDoc() == mDocument) {
757 sDragOverContent = nullptr;
758 }
759
760 if (!m_haveShutdown) {
761 Shutdown();
762
763 // Don't remove from Observer service in Shutdown because Shutdown also
764 // gets called from xpcom shutdown observer. And we don't want to remove
765 // from the service in that case.
766
767 nsCOMPtr<nsIObserverService> observerService =
768 mozilla::services::GetObserverService();
769 if (observerService) {
770 observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
771 }
772 }
773}
774
775void EventStateManager::Shutdown() { m_haveShutdown = true; }
776
777NS_IMETHODIMPnsresult
778EventStateManager::Observe(nsISupports* aSubject, const char* aTopic,
779 const char16_t* someData) {
780 if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown")) {
781 Shutdown();
782 }
783
784 return NS_OK;
785}
786
787NS_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"
, 787); 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
788 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
789 NS_INTERFACE_MAP_ENTRY(nsIObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIObserver>)) foundInterface = static_cast
<nsIObserver*>(this); else
790 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
791NS_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"
, 791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 791); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
792
793NS_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"
, 793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 793
); __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; }
794NS_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"
, 794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 794
); __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); }
795
796NS_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); 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); (void)tmp; return NS_OK;
}
797 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); 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); (void)tmp; return NS_OK;
}
798 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); 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); (void)tmp; return NS_OK;
}
799 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); 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); (void)tmp; return NS_OK;
}
800 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); 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); (void)tmp; return NS_OK;
}
801 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); 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); (void)tmp; return NS_OK;
}
802 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); 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); (void)tmp; return NS_OK;
}
803 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); 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); (void)tmp; return NS_OK;
}
804 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); 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); (void)tmp; return NS_OK;
}
805 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); 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); (void)tmp; return NS_OK;
}
806 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); 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); (void)tmp; return NS_OK;
}
807 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); 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); (void)tmp; return NS_OK;
}
808 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); 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); (void)tmp; return NS_OK;
}
809
810void EventStateManager::ReleaseCurrentIMEContentObserver() {
811 if (mIMEContentObserver) {
812 mIMEContentObserver->DisconnectFromEventStateManager();
813 }
814 mIMEContentObserver = nullptr;
815}
816
817void EventStateManager::OnStartToObserveContent(
818 IMEContentObserver* aIMEContentObserver) {
819 if (mIMEContentObserver == aIMEContentObserver) {
820 return;
821 }
822 ReleaseCurrentIMEContentObserver();
823 mIMEContentObserver = aIMEContentObserver;
824}
825
826void EventStateManager::OnStopObservingContent(
827 IMEContentObserver* aIMEContentObserver) {
828 aIMEContentObserver->DisconnectFromEventStateManager();
829 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"
, 829); return; } } while (false)
;
830 mIMEContentObserver = nullptr;
831}
832
833void EventStateManager::TryToFlushPendingNotificationsToIME() {
834 if (mIMEContentObserver) {
835 mIMEContentObserver->TryToFlushPendingNotifications(true);
836 }
837}
838
839static bool IsMessageMouseUserActivity(EventMessage aMessage) {
840 return aMessage == eMouseMove || aMessage == eMouseUp ||
841 aMessage == eMouseDown || aMessage == ePointerAuxClick ||
842 aMessage == eMouseDoubleClick || aMessage == ePointerClick ||
843 aMessage == eMouseActivate || aMessage == eMouseLongTap;
844}
845
846static bool IsMessageGamepadUserActivity(EventMessage aMessage) {
847 return aMessage == eGamepadButtonDown || aMessage == eGamepadButtonUp ||
848 aMessage == eGamepadAxisMove;
849}
850
851// static
852bool EventStateManager::IsKeyboardEventUserActivity(WidgetEvent* aEvent) {
853 // We ignore things that shouldn't cause popups, but also things that look
854 // like shortcut presses. In some obscure cases these may actually be
855 // website input, but any meaningful website will have other input anyway,
856 // and we can't very well tell whether shortcut input was supposed to be
857 // directed at chrome or the document.
858
859 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
860 // Access keys should be treated as page interaction.
861 if (keyEvent->ModifiersMatchWithAccessKey(AccessKeyType::eContent)) {
862 return true;
863 }
864 if (!keyEvent->CanTreatAsUserInput() || keyEvent->IsControl() ||
865 keyEvent->IsMeta() || keyEvent->IsAlt()) {
866 return false;
867 }
868 // Deal with function keys:
869 switch (keyEvent->mKeyNameIndex) {
870 case KEY_NAME_INDEX_F1:
871 case KEY_NAME_INDEX_F2:
872 case KEY_NAME_INDEX_F3:
873 case KEY_NAME_INDEX_F4:
874 case KEY_NAME_INDEX_F5:
875 case KEY_NAME_INDEX_F6:
876 case KEY_NAME_INDEX_F7:
877 case KEY_NAME_INDEX_F8:
878 case KEY_NAME_INDEX_F9:
879 case KEY_NAME_INDEX_F10:
880 case KEY_NAME_INDEX_F11:
881 case KEY_NAME_INDEX_F12:
882 case KEY_NAME_INDEX_F13:
883 case KEY_NAME_INDEX_F14:
884 case KEY_NAME_INDEX_F15:
885 case KEY_NAME_INDEX_F16:
886 case KEY_NAME_INDEX_F17:
887 case KEY_NAME_INDEX_F18:
888 case KEY_NAME_INDEX_F19:
889 case KEY_NAME_INDEX_F20:
890 case KEY_NAME_INDEX_F21:
891 case KEY_NAME_INDEX_F22:
892 case KEY_NAME_INDEX_F23:
893 case KEY_NAME_INDEX_F24:
894 return false;
895 default:
896 return true;
897 }
898}
899
900static void OnTypingInteractionEnded() {
901 // We don't consider a single keystroke to be typing.
902 if (gTypingInteractionKeyPresses > 1) {
903 gTypingInteraction.mInteractionCount += gTypingInteractionKeyPresses;
904 gTypingInteraction.mInteractionTimeInMilliseconds += static_cast<uint32_t>(
905 std::ceil((gTypingEndTime - gTypingStartTime).ToMilliseconds()));
906 }
907
908 gTypingInteractionKeyPresses = 0;
909 gTypingStartTime = TimeStamp();
910 gTypingEndTime = TimeStamp();
911}
912
913static void HandleKeyUpInteraction(WidgetKeyboardEvent* aKeyEvent) {
914 if (EventStateManager::IsKeyboardEventUserActivity(aKeyEvent)) {
915 TimeStamp now = TimeStamp::Now();
916 if (gTypingEndTime.IsNull()) {
917 gTypingEndTime = now;
918 }
919 TimeDuration delay = now - gTypingEndTime;
920 // Has it been too long since the last keystroke to be considered typing?
921 if (gTypingInteractionKeyPresses > 0 &&
922 delay >
923 TimeDuration::FromMilliseconds(
924 StaticPrefs::browser_places_interactions_typing_timeout_ms())) {
925 OnTypingInteractionEnded();
926 }
927 gTypingInteractionKeyPresses++;
928 if (gTypingStartTime.IsNull()) {
929 gTypingStartTime = now;
930 }
931 gTypingEndTime = now;
932 }
933}
934
935static bool NeedsActiveContentChange(const WidgetMouseEvent* aMouseEvent) {
936 // If the mouse event is a synthesized mouse event due to a touch, do
937 // not set/clear the activation state. Element activation is handled by APZ.
938 return !aMouseEvent ||
939 aMouseEvent->mInputSource != MouseEvent_Binding::MOZ_SOURCE_TOUCH;
940}
941
942nsresult EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
943 WidgetEvent* aEvent,
944 nsIFrame* aTargetFrame,
945 nsIContent* aTargetContent,
946 nsEventStatus* aStatus,
947 nsIContent* aOverrideClickTarget) {
948 AUTO_PROFILER_LABEL("EventStateManager::PreHandleEvent", DOM)mozilla::AutoProfilerLabel raiiObject948( "EventStateManager::PreHandleEvent"
, nullptr, JS::ProfilingCategoryPair::DOM)
;
949 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", 949
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
950 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"
, 950); return NS_ERROR_INVALID_ARG; } } while (false)
;
951 if (!aEvent) {
952 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"
, 952); MOZ_PretendNoReturn(); } while (0)
;
953 return NS_ERROR_NULL_POINTER;
954 }
955
956 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", 962
); } } while (false)
957 !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", 962
); } } while (false)
958 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", 962
); } } while (false)
959 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", 962
); } } while (false)
960 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", 962
); } } while (false)
961 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", 962
); } } while (false)
962 "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", 962
); } } while (false)
;
963#if DEBUG1
964 if (aTargetFrame && aTargetFrame->IsGeneratedContentFrame()) {
965 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"
, 967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent)"
") (" "Unexpected target for generated content frame!" ")");
do { MOZ_CrashSequence(__null, 967); __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
966 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"
, 967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent)"
") (" "Unexpected target for generated content frame!" ")");
do { MOZ_CrashSequence(__null, 967); __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
967 "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"
, 967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent)"
") (" "Unexpected target for generated content frame!" ")");
do { MOZ_CrashSequence(__null, 967); __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
968 }
969#endif
970
971 mCurrentTarget = aTargetFrame;
972 mCurrentTargetContent = nullptr;
973
974 // Do not take account eMouseEnterIntoWidget/ExitFromWidget so that loading
975 // a page when user is not active doesn't change the state to active.
976 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
977 if (aEvent->IsTrusted() &&
978 ((mouseEvent && mouseEvent->IsReal() &&
979 IsMessageMouseUserActivity(mouseEvent->mMessage)) ||
980 aEvent->mClass == eWheelEventClass ||
981 aEvent->mClass == ePointerEventClass ||
982 aEvent->mClass == eTouchEventClass ||
983 aEvent->mClass == eKeyboardEventClass ||
984 (aEvent->mClass == eDragEventClass && aEvent->mMessage == eDrop) ||
985 IsMessageGamepadUserActivity(aEvent->mMessage))) {
986 if (gMouseOrKeyboardEventCounter == 0) {
987 nsCOMPtr<nsIObserverService> obs =
988 mozilla::services::GetObserverService();
989 if (obs) {
990 obs->NotifyObservers(nullptr, "user-interaction-active", nullptr);
991 UpdateUserActivityTimer();
992 }
993 }
994 ++gMouseOrKeyboardEventCounter;
995
996 // Synthesized mouse/pointer events (e.g. a synthesized pointer move when
997 // content moves under a stationary cursor) are not real user activity, so
998 // they are excluded from the corrected active tick.
999 if (!mouseEvent || mouseEvent->IsReal()) {
1000 if (gNonSynthesizedMouseOrKeyboardEventCounter == 0) {
1001 nsCOMPtr<nsIObserverService> obs =
1002 mozilla::services::GetObserverService();
1003 if (obs) {
1004 obs->NotifyObservers(
1005 nullptr, "user-interaction-active-non-synthesized", nullptr);
1006 }
1007 }
1008 ++gNonSynthesizedMouseOrKeyboardEventCounter;
1009 }
1010
1011 nsCOMPtr<nsINode> node = aTargetContent;
1012 if (node &&
1013 ((aEvent->mMessage == eKeyUp && IsKeyboardEventUserActivity(aEvent)) ||
1014 aEvent->mMessage == eMouseUp || aEvent->mMessage == eWheel ||
1015 aEvent->mMessage == eTouchEnd || aEvent->mMessage == ePointerUp ||
1016 aEvent->mMessage == eDrop)) {
1017 Document* doc = node->OwnerDoc();
1018 while (doc) {
1019 doc->SetUserHasInteracted();
1020 doc = nsContentUtils::IsChildOfSameType(doc)
1021 ? doc->GetInProcessParentDocument()
1022 : nullptr;
1023 }
1024 }
1025 }
1026
1027 WheelTransaction::OnEvent(aEvent);
1028
1029 // Focus events don't necessarily need a frame.
1030 if (!mCurrentTarget && !aTargetContent) {
1031 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"
, 1031); MOZ_PretendNoReturn(); } while (0)
;
1032 return NS_ERROR_NULL_POINTER;
1033 }
1034#ifdef DEBUG1
1035 if (aEvent->HasDragEventMessage() && PointerLockManager::IsLocked()) {
1036 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"
, 1038); MOZ_PretendNoReturn(); } } while (0)
1037 "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"
, 1038); MOZ_PretendNoReturn(); } } while (0)
1038 "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"
, 1038); MOZ_PretendNoReturn(); } } while (0)
;
1039 }
1040#endif
1041 // Store last known screenPoint and clientPoint so pointer lock
1042 // can use these values as constants.
1043 if (aEvent->IsTrusted() &&
1044 ((mouseEvent && mouseEvent->IsReal()) ||
1045 aEvent->mClass == eWheelEventClass) &&
1046 !PointerLockManager::IsLocked()) {
1047 // XXX Probably doesn't matter much, but storing these in CSS pixels instead
1048 // of device pixels means behavior can be a bit odd if you zoom while
1049 // pointer-locked.
1050 sLastScreenPoint = RoundedToInt(
1051 Event::GetScreenCoords(aPresContext, aEvent, aEvent->mRefPoint)
1052 .extract());
1053 sLastClientPoint = RoundedToInt(Event::GetClientCoords(
1054 aPresContext, aEvent, aEvent->mRefPoint, CSSDoublePoint{0, 0}));
1055 }
1056
1057 *aStatus = nsEventStatus_eIgnore;
1058
1059 if (aEvent->mClass == eQueryContentEventClass) {
1060 HandleQueryContentEvent(aEvent->AsQueryContentEvent());
1061 return NS_OK;
1062 }
1063
1064 WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
1065 if (touchEvent && mInTouchDrag) {
1066 if (touchEvent->mMessage == eTouchMove) {
1067 GenerateDragGesture(aPresContext, *touchEvent);
1068 } else {
1069 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", 1069
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "touchEvent->mMessage != eTouchRawUpdate"
")"); do { MOZ_CrashSequence(__null, 1069); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1070 mInTouchDrag = false;
1071 StopTrackingDragGesture(true);
1072 }
1073 }
1074
1075 if (mMouseEnterLeaveHelper && aEvent->IsTrusted()) {
1076 // When the last `mouseover` event target is removed from the document,
1077 // we makes mMouseEnterLeaveHelper update the last deepest `mouseenter`
1078 // event target to the removed node parent and mark it as not the following
1079 // `mouseout` event target. However, the other browsers may dispatch
1080 // `mouseout` on it if it's restored "immediately". Therefore, we use
1081 // the next animation frame as the deadline. ContentRemoved() enqueues a
1082 // synthesized `mousemove` to dispatch mouse boundary events under the
1083 // mouse cursor soon and the synthesized event (or eMouseExitFromWidget if
1084 // our window is moved) will reach here at latest the next animation frame.
1085 // Therefore, we can use the event as the deadline. If the removed last
1086 // `mouseover` target is reconnected before a synthesized mouse event or
1087 // a real mouse event, let's restore it as the following `mouseout` event
1088 // target. Otherwise, e.g., a keyboard event, let's forget it.
1089 mMouseEnterLeaveHelper->TryToRestorePendingRemovedOverTarget(aEvent);
1090 }
1091
1092 static constexpr auto const allowSynthesisForTests = []() -> bool {
1093 nsCOMPtr<nsIDragService> dragService =
1094 do_GetService("@mozilla.org/widget/dragservice;1");
1095 return dragService &&
1096 !dragService->GetNeverAllowSessionIsSynthesizedForTests();
1097 };
1098
1099 switch (aEvent->mMessage) {
1100 case eContextMenu:
1101 if (PointerLockManager::IsLocked()) {
1102 return NS_ERROR_DOM_INVALID_STATE_ERR;
1103 }
1104 break;
1105 case eMouseTouchDrag:
1106 mInTouchDrag = true;
1107 BeginTrackingDragGesture(aPresContext, *mouseEvent, aTargetFrame);
1108 break;
1109 case eMouseDown: {
1110 switch (mouseEvent->mButton) {
1111 case MouseButton::ePrimary:
1112 BeginTrackingDragGesture(aPresContext, *mouseEvent, aTargetFrame);
1113 mLastPrimaryButtonPressInfo.mClickCount = mouseEvent->mClickCount;
1114 PrepareForFollowingClickEvent(*mouseEvent);
1115 sNormalLMouseEventInProcess = true;
1116 break;
1117 case MouseButton::eMiddle:
1118 mLastMiddleButtonPressInfo.mClickCount = mouseEvent->mClickCount;
1119 PrepareForFollowingClickEvent(*mouseEvent);
1120 break;
1121 case MouseButton::eSecondary:
1122 mLastSecondaryButtonPressInfo.mClickCount = mouseEvent->mClickCount;
1123 PrepareForFollowingClickEvent(*mouseEvent);
1124 break;
1125 case MouseButton::eX1:
1126 case MouseButton::eX2:
1127 // XXX FIXME: We won't dispatch `auxclick` for 4th nor 5th button.
1128 break;
1129 default:
1130 break;
1131 }
1132 break;
1133 }
1134 case eMouseUp: {
1135 switch (mouseEvent->mButton) {
1136 case MouseButton::ePrimary:
1137 if (StaticPrefs::ui_click_hold_context_menus()) {
1138 KillClickHoldTimer();
1139 }
1140 mInTouchDrag = false;
1141 StopTrackingDragGesture(true);
1142 sNormalLMouseEventInProcess = false;
1143 // then fall through...
1144 [[fallthrough]];
1145 case MouseButton::eSecondary:
1146 case MouseButton::eMiddle: {
1147 RefPtr<EventStateManager> esm =
1148 ESMFromContentOrThis(aOverrideClickTarget);
1149 esm->PrepareForFollowingClickEvent(*mouseEvent, aOverrideClickTarget);
1150 break;
1151 }
1152 case MouseButton::eX1:
1153 case MouseButton::eX2:
1154 // XXX FIXME: We won't dispatch `auxclick` for 4th nor 5th button.
1155 break;
1156 default:
1157 break;
1158 }
1159 break;
1160 }
1161 case eMouseEnterIntoWidget:
1162 PointerEventHandler::UpdatePointerActiveState(mouseEvent, aTargetContent);
1163 // In some cases on e10s eMouseEnterIntoWidget
1164 // event was sent twice into child process of content.
1165 // (From specific widget code (sending is not permanent) and
1166 // from ESM::DispatchMouseOrPointerBoundaryEvent (sending is permanent)).
1167 // IsCrossProcessForwardingStopped() helps to suppress sending accidental
1168 // event from widget code.
1169 aEvent->StopCrossProcessForwarding();
1170 break;
1171 case eMouseExitFromWidget:
1172 // If this is a remote frame, we receive eMouseExitFromWidget from the
1173 // parent the mouse exits our content. Since the parent may update the
1174 // cursor while the mouse is outside our frame, and since PuppetWidget
1175 // caches the current cursor internally, re-entering our content (say from
1176 // over a window edge) wont update the cursor if the cached value and the
1177 // current cursor match. So when the mouse exits a remote frame, clear the
1178 // cached widget cursor so a proper update will occur when the mouse
1179 // re-enters.
1180 if (XRE_IsContentProcess()) {
1181 ClearCachedWidgetCursor(mCurrentTarget);
1182 }
1183
1184 // IsCrossProcessForwardingStopped() helps to suppress double event
1185 // sending into process of content. For more information see comment
1186 // above, at eMouseEnterIntoWidget case.
1187 aEvent->StopCrossProcessForwarding();
1188
1189 // If the event is not a top-level window or puppet widget exit, then it's
1190 // not really an exit --- we may have traversed widget boundaries but
1191 // we're still in our toplevel window or puppet widget.
1192 if (mouseEvent->mExitFrom.value() !=
1193 WidgetMouseEvent::ePlatformTopLevel &&
1194 mouseEvent->mExitFrom.value() != WidgetMouseEvent::ePuppet) {
1195 // Treat it as a synthetic move so we don't generate spurious
1196 // "exit" or "move" events. Any necessary "out" or "over" events
1197 // will be generated by GenerateMouseEnterExit
1198 mouseEvent->mMessage = eMouseMove;
1199 mouseEvent->mReason = WidgetMouseEvent::eSynthesized;
1200 // We need to generate pointer boundary events here because there is no
1201 // preceding pointer event dispatched for the eMouseExitFromWidget
1202 // event.
1203 GeneratePointerEnterExit(ePointerMove, mouseEvent);
1204 // then fall through...
1205 } else {
1206 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", 1208
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel"
")"); do { MOZ_CrashSequence(__null, 1208); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1207 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", 1208
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel"
")"); do { MOZ_CrashSequence(__null, 1208); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1208 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", 1208
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel"
")"); do { MOZ_CrashSequence(__null, 1208); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1209 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", 1210
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet"
")"); do { MOZ_CrashSequence(__null, 1210); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1210 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", 1210
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet"
")"); do { MOZ_CrashSequence(__null, 1210); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1211 // We should synthetize corresponding pointer events
1212 GeneratePointerEnterExit(ePointerLeave, mouseEvent);
1213 GenerateMouseEnterExit(mouseEvent);
1214 // Remove the pointer from the active pointerId table.
1215 PointerEventHandler::UpdatePointerActiveState(mouseEvent);
1216 // This is really an exit and should stop here
1217 aEvent->mMessage = eVoidEvent;
1218 break;
1219 }
1220 [[fallthrough]];
1221 case ePointerDown:
1222 if (aEvent->mMessage == ePointerDown) {
1223 PointerEventHandler::UpdatePointerActiveState(mouseEvent,
1224 aTargetContent);
1225 PointerEventHandler::ImplicitlyCapturePointer(aTargetFrame, *aEvent);
1226 // https://html.spec.whatwg.org/multipage/interaction.html#activation-triggering-input-event
1227 if (mouseEvent->mInputSource == MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
1228 NotifyTargetUserActivation(aEvent, aTargetContent);
1229 }
1230
1231 LightDismissOpenPopovers(aEvent, aTargetContent);
1232 LightDismissOpenDialogs(aEvent, aTargetContent);
1233 }
1234 [[fallthrough]];
1235 case eMouseMove:
1236 case ePointerMove:
1237 case ePointerRawUpdate: {
1238 if (aEvent->mMessage == ePointerMove) {
1239 PointerEventHandler::UpdatePointerActiveState(mouseEvent,
1240 aTargetContent);
1241 }
1242 if (!mInTouchDrag &&
1243 PointerEventHandler::IsDragAndDropEnabled(*mouseEvent)) {
1244 GenerateDragGesture(aPresContext, *mouseEvent);
1245 }
1246 // on the Mac, GenerateDragGesture() may not return until the drag
1247 // has completed and so |aTargetFrame| may have been deleted (moving
1248 // a bookmark, for example). If this is the case, however, we know
1249 // that ClearFrameRefs() has been called and it cleared out
1250 // |mCurrentTarget|. As a result, we should pass |mCurrentTarget|
1251 // into UpdateCursor().
1252 UpdateCursor(aPresContext, mouseEvent, mCurrentTarget, aStatus);
1253
1254 UpdateLastRefPointOfMouseEvent(mouseEvent);
1255 ResetPointerToWindowCenterWhilePointerLocked(mouseEvent);
1256 UpdateLastPointerPosition(mouseEvent);
1257
1258 GenerateMouseEnterExit(mouseEvent);
1259 // Flush pending layout changes, so that later mouse move events
1260 // will go to the right nodes.
1261 FlushLayout(aPresContext);
1262
1263 if (aEvent->mMessage == ePointerDown &&
1264 NeedsActiveContentChange(mouseEvent)) {
1265 nsCOMPtr<nsIContent> activeContent =
1266 mCurrentTarget ? mCurrentTarget->GetContent() : nullptr;
1267 if (activeContent && !activeContent->IsElement()) {
1268 if (nsIContent* parent = activeContent->GetFlattenedTreeParent()) {
1269 activeContent = parent;
1270 }
1271 }
1272 SetActiveManager(this, activeContent);
1273 }
1274 break;
1275 }
1276 case ePointerUp:
1277 LightDismissOpenPopovers(aEvent, aTargetContent);
1278 LightDismissOpenDialogs(aEvent, aTargetContent);
1279 GenerateMouseEnterExit(mouseEvent);
1280 if (mouseEvent->mInputSource != MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
1281 NotifyTargetUserActivation(aEvent, aTargetContent);
1282 }
1283 if (NeedsActiveContentChange(mouseEvent)) {
1284 ClearGlobalActiveContent(this);
1285 }
1286 break;
1287 case ePointerGotCapture:
1288 GenerateMouseEnterExit(mouseEvent);
1289 break;
1290 case eDragStart:
1291 if (StaticPrefs::ui_click_hold_context_menus()) {
1292 // an external drag gesture event came in, not generated internally
1293 // by Gecko. Make sure we get rid of the click-hold timer.
1294 KillClickHoldTimer();
1295 }
1296 break;
1297 case eDragOver: {
1298 WidgetDragEvent* dragEvent = aEvent->AsDragEvent();
1299 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"
, 1299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dragEvent" ")"
); do { MOZ_CrashSequence(__null, 1299); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1300 if (dragEvent->mFlags.mIsSynthesizedForTests &&
1301 allowSynthesisForTests()) {
1302 dragEvent->InitDropEffectForTests();
1303 }
1304 // Send the enter/exit events before eDrop.
1305 GenerateDragDropEnterExit(aPresContext, *dragEvent);
1306 break;
1307 }
1308 case eDrop: {
1309 if (aEvent->mFlags.mIsSynthesizedForTests && allowSynthesisForTests()) {
1310 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", 1310
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->AsDragEvent()"
")"); do { MOZ_CrashSequence(__null, 1310); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1311 aEvent->AsDragEvent()->InitDropEffectForTests();
1312 }
1313 break;
1314 }
1315 case eKeyPress: {
1316 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
1317 if ((keyEvent->ModifiersMatchWithAccessKey(AccessKeyType::eChrome) ||
1318 keyEvent->ModifiersMatchWithAccessKey(AccessKeyType::eContent)) &&
1319 // If the key binding of this event is a native key binding, we
1320 // prioritize it.
1321 !HasNativeKeyBindings(aTargetContent, keyEvent)) {
1322 // If the eKeyPress event will be sent to a remote process, this
1323 // process needs to wait reply from the remote process for checking if
1324 // preceding eKeyDown event is consumed. If preceding eKeyDown event
1325 // is consumed in the remote process, BrowserChild won't send the event
1326 // back to this process. So, only when this process receives a reply
1327 // eKeyPress event in BrowserParent, we should handle accesskey in this
1328 // process.
1329 if (IsTopLevelRemoteTarget(GetFocusedElement())) {
1330 // However, if there is no accesskey target for the key combination,
1331 // we don't need to wait reply from the remote process. Otherwise,
1332 // Mark the event as waiting reply from remote process and stop
1333 // propagation in this process.
1334 if (CheckIfEventMatchesAccessKey(keyEvent, aPresContext)) {
1335 keyEvent->StopPropagation();
1336 keyEvent->MarkAsWaitingReplyFromRemoteProcess();
1337 }
1338 }
1339 // If the event target is in this process, we can handle accesskey now
1340 // since if preceding eKeyDown event was consumed, eKeyPress event
1341 // won't be dispatched by widget. So, coming eKeyPress event means
1342 // that the preceding eKeyDown event wasn't consumed in this case.
1343 else {
1344 AutoTArray<uint32_t, 10> accessCharCodes;
1345 keyEvent->GetAccessKeyCandidates(accessCharCodes);
1346
1347 if (HandleAccessKey(keyEvent, aPresContext, accessCharCodes)) {
1348 *aStatus = nsEventStatus_eConsumeNoDefault;
1349 }
1350 }
1351 }
1352 }
1353 // then fall through...
1354 [[fallthrough]];
1355 case eKeyDown:
1356 if (aEvent->mMessage == eKeyDown) {
1357 NotifyTargetUserActivation(aEvent, aTargetContent);
1358 }
1359 [[fallthrough]];
1360 case eKeyUp: {
1361 Element* element = GetFocusedElement();
1362 if (element) {
1363 mCurrentTargetContent = element;
1364 }
1365
1366 // NOTE: Don't refer TextComposition::IsComposing() since UI Events
1367 // defines that KeyboardEvent.isComposing is true when it's
1368 // dispatched after compositionstart and compositionend.
1369 // TextComposition::IsComposing() is false even before
1370 // compositionend if there is no composing string.
1371 // And also don't expose other document's composition state.
1372 // A native IME context is typically shared by multiple documents.
1373 // So, don't use GetTextCompositionFor(nsIWidget*) here.
1374 RefPtr<TextComposition> composition =
1375 IMEStateManager::GetTextCompositionFor(aPresContext);
1376 aEvent->AsKeyboardEvent()->mIsComposing = !!composition;
1377
1378 // Widget may need to perform default action for specific keyboard
1379 // event if it's not consumed. In this case, widget has already marked
1380 // the event as "waiting reply from remote process". However, we need
1381 // to reset it if the target (focused content) isn't in a remote process
1382 // because PresShell needs to check if it's marked as so before
1383 // dispatching events into the DOM tree.
1384 if (aEvent->IsWaitingReplyFromRemoteProcess() &&
1385 !aEvent->PropagationStopped() && !IsTopLevelRemoteTarget(element)) {
1386 aEvent->ResetWaitingReplyFromRemoteProcessState();
1387 }
1388 } break;
1389 case eWheel:
1390 case eWheelOperationStart:
1391 case eWheelOperationEnd: {
1392 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", 1393
); MOZ_PretendNoReturn(); } } while (0)
1393 "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", 1393
); MOZ_PretendNoReturn(); } } while (0)
;
1394 using DeltaModeCheckingState = WidgetWheelEvent::DeltaModeCheckingState;
1395
1396 if (Element* element = GetFocusedElement()) {
1397 mCurrentTargetContent = element;
1398 }
1399
1400 if (aEvent->mMessage != eWheel) {
1401 break;
1402 }
1403
1404 WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent();
1405 WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(wheelEvent);
1406
1407 // If we won't dispatch a DOM event for this event, nothing to do anymore.
1408 if (!wheelEvent->IsAllowedToDispatchDOMEvent()) {
1409 break;
1410 }
1411
1412 if (StaticPrefs::dom_event_wheel_deltaMode_lines_always_disabled()) {
1413 wheelEvent->mDeltaModeCheckingState = DeltaModeCheckingState::Unchecked;
1414 } else if (ShouldAlwaysUseLineDeltas()) {
1415 wheelEvent->mDeltaModeCheckingState = DeltaModeCheckingState::Checked;
1416 } else {
1417 wheelEvent->mDeltaModeCheckingState = DeltaModeCheckingState::Unknown;
1418 }
1419
1420 // Init lineOrPageDelta values for line scroll events for some devices
1421 // on some platforms which might dispatch wheel events which don't
1422 // have lineOrPageDelta values. And also, if delta values are
1423 // customized by prefs, this recomputes them.
1424 DeltaAccumulator::GetInstance()->InitLineOrPageDelta(aTargetFrame, this,
1425 wheelEvent);
1426 } break;
1427 case eSetSelection: {
1428 RefPtr<Element> focuedElement = GetFocusedElement();
1429 IMEStateManager::HandleSelectionEvent(aPresContext, focuedElement,
1430 aEvent->AsSelectionEvent());
1431 break;
1432 }
1433 case eContentCommandCut:
1434 case eContentCommandCopy:
1435 case eContentCommandPaste:
1436 case eContentCommandDelete:
1437 case eContentCommandUndo:
1438 case eContentCommandRedo:
1439 case eContentCommandPasteTransferable:
1440 case eContentCommandLookUpDictionary:
1441 DoContentCommandEvent(aEvent->AsContentCommandEvent());
1442 break;
1443 case eContentCommandInsertText:
1444 DoContentCommandInsertTextEvent(aEvent->AsContentCommandEvent());
1445 break;
1446 case eContentCommandReplaceText:
1447 DoContentCommandReplaceTextEvent(aEvent->AsContentCommandEvent());
1448 break;
1449 case eContentCommandScroll:
1450 DoContentCommandScrollEvent(aEvent->AsContentCommandEvent());
1451 break;
1452 case eCompositionStart:
1453 if (aEvent->IsTrusted()) {
1454 // If the event is trusted event, set the selected text to data of
1455 // composition event.
1456 WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent();
1457 WidgetQueryContentEvent querySelectedTextEvent(
1458 true, eQuerySelectedText, compositionEvent->mWidget);
1459 HandleQueryContentEvent(&querySelectedTextEvent);
1460 if (querySelectedTextEvent.FoundSelection()) {
1461 compositionEvent->mData = querySelectedTextEvent.mReply->DataRef();
1462 }
1463 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", 1464
); MOZ_PretendNoReturn(); } } while (0)
1464 "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", 1464
); MOZ_PretendNoReturn(); } } while (0)
;
1465 }
1466 break;
1467 case eTouchStart:
1468 SetGestureDownPoint(*aEvent->AsTouchEvent());
1469 break;
1470 default:
1471 break;
1472 }
1473 return NS_OK;
1474}
1475
1476// Returns true if this event is likely an user activation for a link or
1477// a link-like button, where modifier keys are likely be used for controlling
1478// where the link is opened.
1479//
1480// The modifiers associated with the user activation is used for controlling
1481// where the `window.open` is opened into.
1482static bool CanReflectModifiersToUserActivation(WidgetInputEvent* aEvent) {
1483 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", 1484
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1484); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1484 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", 1484
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1484); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1485
1486 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
1487 if (keyEvent) {
1488 return keyEvent->CanReflectModifiersToUserActivation();
1489 }
1490
1491 return true;
1492}
1493
1494void EventStateManager::NotifyTargetUserActivation(WidgetEvent* aEvent,
1495 nsIContent* aTargetContent) {
1496 if (!aEvent->IsTrusted()) {
1497 return;
1498 }
1499
1500 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
1501 if (mouseEvent && !mouseEvent->IsReal()) {
1502 return;
1503 }
1504
1505 nsCOMPtr<nsINode> node = aTargetContent;
1506 if (!node) {
1507 return;
1508 }
1509
1510 Document* doc = node->OwnerDoc();
1511 if (!doc) {
1512 return;
1513 }
1514
1515 // Don't gesture activate for key events for keys which are likely
1516 // to be interaction with the browser, OS.
1517 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
1518 if (keyEvent && !keyEvent->CanUserGestureActivateTarget()) {
1519 return;
1520 }
1521
1522 // Do not treat the click on scrollbar as a user interaction with the web
1523 // content.
1524 if (StaticPrefs::dom_user_activation_ignore_scrollbars() &&
1525 (aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp) &&
1526 aTargetContent->IsInNativeAnonymousSubtree()) {
1527 nsIContent* current = aTargetContent;
1528 do {
1529 nsIContent* root = current->GetClosestNativeAnonymousSubtreeRoot();
1530 if (!root) {
1531 break;
1532 }
1533 if (root->IsXULElement(nsGkAtoms::scrollbar)) {
1534 return;
1535 }
1536 current = root->GetParent();
1537 } while (current);
1538 }
1539
1540 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", 1541
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1541 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", 1541
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1542
1543 UserActivation::Modifiers modifiers;
1544 if (WidgetInputEvent* inputEvent = aEvent->AsInputEvent()) {
1545 if (CanReflectModifiersToUserActivation(inputEvent)) {
1546 if (inputEvent->IsShift()) {
1547 modifiers.SetShift();
1548 }
1549 if (inputEvent->IsMeta()) {
1550 modifiers.SetMeta();
1551 }
1552 if (inputEvent->IsControl()) {
1553 modifiers.SetControl();
1554 }
1555 if (inputEvent->IsAlt()) {
1556 modifiers.SetAlt();
1557 }
1558
1559 WidgetMouseEvent* mouseEvent = inputEvent->AsMouseEvent();
1560 if (mouseEvent) {
1561 if (mouseEvent->mButton == MouseButton::eMiddle) {
1562 modifiers.SetMiddleMouse();
1563 }
1564 }
1565 }
1566 }
1567 doc->NotifyUserGestureActivation(modifiers);
1568}
1569
1570// https://html.spec.whatwg.org/multipage/popover.html#popover-light-dismiss
1571void EventStateManager::LightDismissOpenPopovers(WidgetEvent* aEvent,
1572 nsIContent* aTargetContent) {
1573 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",
1574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
") (" "Light dismiss must be called for pointer up/down only"
")"); do { MOZ_CrashSequence(__null, 1574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1574 "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",
1574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
") (" "Light dismiss must be called for pointer up/down only"
")"); do { MOZ_CrashSequence(__null, 1574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1575
1576 // 1. Assert: event's isTrusted attribute is true.
1577 if (!aEvent->IsTrusted() || !aTargetContent) {
1578 return;
1579 }
1580
1581 // 2. Let target be event's target.
1582
1583 // 3. Let document be target's node document.
1584 RefPtr<Document> targetDoc(aTargetContent->OwnerDoc());
1585
1586 // 4. If the result of running topmost auto or hint popover given document is
1587 // null, then return.
1588 RefPtr<Element> topmostPopover =
1589 targetDoc->GetTopmostPopoverOf(PopoverAttributeState::Hint);
1590 if (!topmostPopover) {
1591 topmostPopover =
1592 targetDoc->GetTopmostPopoverOf(PopoverAttributeState::Auto);
1593 }
1594 if (!topmostPopover) {
1595 return;
1596 }
1597
1598 // 5. If event's type is "pointerdown": set document's popover pointerdown
1599 // target to the result of running topmost clicked popover given target.
1600 if (aEvent->mMessage == ePointerDown) {
1601 mPopoverPointerDownTarget = aTargetContent->GetTopmostClickedPopover();
1602 return;
1603 }
1604 // 6. If event's type is "pointerup":
1605
1606 // 6.1. Let ancestor be the result of running topmost clicked popover given
1607 // target.
1608 RefPtr<Element> ancestor = aTargetContent->GetTopmostClickedPopover();
1609
1610 // 6.2. Let sameTarget be true if ancestor is document's popover pointerdown
1611 // target.
1612 bool sameTarget =
1613 mPopoverPointerDownTarget == static_cast<nsINode*>(ancestor.get());
1614
1615 // 6.3. Set document's popover pointerdown target to null.
1616 mPopoverPointerDownTarget = nullptr;
1617
1618 // 6.4. If sameTarget is false, then return.
1619 if (!sameTarget) {
1620 return;
1621 }
1622
1623 // 6.5. Run hide popovers until given document, ancestor, false, and true.
1624 targetDoc->HidePopoversUntil(ancestor, false, true);
1625}
1626
1627// https://html.spec.whatwg.org/multipage/interactive-elements.html#run-light-dismiss-activities
1628// https://html.spec.whatwg.org/multipage/interactive-elements.html#light-dismiss-open-dialogs
1629void EventStateManager::LightDismissOpenDialogs(WidgetEvent* aEvent,
1630 nsIContent* aTargetContent) {
1631 // 1. Assert: event's isTrusted attribute is true.
1632 // 2. Let document be event's target's node document.
1633 // (Skipped - not applicable)
1634
1635 if (!StaticPrefs::dom_dialog_light_dismiss_enabled()) {
1636 return;
1637 }
1638
1639 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",
1640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
") (" "Light dismiss must be called for pointer up/down only"
")"); do { MOZ_CrashSequence(__null, 1640); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1640 "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",
1640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
") (" "Light dismiss must be called for pointer up/down only"
")"); do { MOZ_CrashSequence(__null, 1640); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1641
1642 if (aEvent->mFlags.mDefaultPrevented || !aEvent->IsTrusted() ||
1643 !aTargetContent) {
1644 return;
1645 }
1646
1647 auto* doc = aTargetContent->OwnerDoc();
1648
1649 // 3. If document's open dialogs list is empty, then return.
1650 if (!doc->HasOpenDialogs()) {
1651 return;
1652 }
1653
1654 // 4. Let ancestor be the result of running nearest clicked dialog given
1655 // event.
1656 RefPtr<HTMLDialogElement> ancestor =
1657 aTargetContent->NearestClickedDialog(aEvent);
1658
1659 // 5. If event's type is "pointerdown", then set document's dialog pointerdown
1660 // target to ancestor.
1661 if (aEvent->mMessage == ePointerDown) {
1662 // XXX: "document's dialog pointerdown target" can be null, but
1663 // `SetLastDialogPointerdownTarget` takes `&` to avoid incidental nullptrs,
1664 // meaning we need to nullcheck `ancestor` & call
1665 // `ClearLastDialogPointerdownTarget` instead.
1666 if (!ancestor) {
1667 doc->ClearLastDialogPointerdownTarget();
1668 } else {
1669 doc->SetLastDialogPointerdownTarget(*ancestor);
1670 }
1671 return;
1672 }
1673
1674 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"
, 1674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1674); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1675
1676 // 6.1 Let sameTarget be true if ancestor is document's dialog pointerdown
1677 // target.
1678 RefPtr<HTMLDialogElement> lastDialog = doc->GetLastDialogPointerdownTarget();
1679 bool sameTarget = ancestor == lastDialog;
1680
1681 // 6.2 Set document's dialog pointerdown target to null.
1682 doc->ClearLastDialogPointerdownTarget();
1683
1684 // 6.3 If sameTarget is false, then return.
1685 if (!sameTarget) {
1686 return;
1687 }
1688
1689 // 6.4 Let topmostDialog be the last element of document's open dialogs list.
1690 RefPtr<HTMLDialogElement> topmostDialog = doc->GetTopMostOpenDialog();
1691
1692 // 6.5 If ancestor is topmostDialog, then return.
1693 if (ancestor == topmostDialog) {
1694 return;
1695 }
1696
1697 // 6.6 If topmostDialog's computed closed-by state is not Any, then return.
1698 if (!topmostDialog ||
1699 topmostDialog->GetClosedBy() != HTMLDialogElement::ClosedBy::Any) {
1700 return;
1701 }
1702
1703 // 7. Assert: topmostDialog's close watcher is not null.
1704
1705 // 8. Request to close topmostDialog's close watcher with false.
1706 const mozilla::dom::Optional<nsAString> returnValue;
1707 topmostDialog->RequestClose(returnValue);
1708}
1709
1710already_AddRefed<EventStateManager> EventStateManager::ESMFromContentOrThis(
1711 nsIContent* aContent) {
1712 if (aContent) {
1713 PresShell* presShell = aContent->OwnerDoc()->GetPresShell();
1714 if (presShell) {
1715 nsPresContext* prescontext = presShell->GetPresContext();
1716 if (prescontext) {
1717 RefPtr<EventStateManager> esm = prescontext->EventStateManager();
1718 if (esm) {
1719 return esm.forget();
1720 }
1721 }
1722 }
1723 }
1724
1725 RefPtr<EventStateManager> esm = this;
1726 return esm.forget();
1727}
1728
1729auto EventStateManager::GetLastMouseButtonPressInfo(int16_t aButton) const
1730 -> const LastMouseButtonPressInfo& {
1731 switch (aButton) {
1732 case MouseButton::ePrimary:
1733 return mLastPrimaryButtonPressInfo;
1734 case MouseButton::eMiddle:
1735 return mLastMiddleButtonPressInfo;
1736 case MouseButton::eSecondary:
1737 return mLastSecondaryButtonPressInfo;
1738 default:
1739 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"
, 1739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "This button shouldn't use this method"
")"); do { MOZ_CrashSequence(__null, 1739); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1740 return mLastPrimaryButtonPressInfo;
1741 }
1742}
1743
1744void EventStateManager::HandleQueryContentEvent(
1745 WidgetQueryContentEvent* aEvent) {
1746 switch (aEvent->mMessage) {
1747 case eQuerySelectedText:
1748 case eQueryTextContent:
1749 case eQueryCaretRect:
1750 case eQueryTextRect:
1751 case eQueryEditorRect:
1752 if (!IsTargetCrossProcess(aEvent)) {
1753 break;
1754 }
1755 // Will not be handled locally, remote the event
1756 GetCrossProcessTarget()->HandleQueryContentEvent(*aEvent);
1757 return;
1758 // Following events have not been supported in e10s mode yet.
1759 case eQueryContentState:
1760 case eQuerySelectionAsTransferable:
1761 case eQueryCharacterAtPoint:
1762 case eQueryDOMWidgetHittest:
1763 case eQueryTextRectArray:
1764 case eQueryDropTargetHittest:
1765 break;
1766 default:
1767 return;
1768 }
1769
1770 // If there is an IMEContentObserver, we need to handle QueryContentEvent
1771 // with it.
1772 // eQueryDropTargetHittest is not really an IME event, though
1773 if (mIMEContentObserver && aEvent->mMessage != eQueryDropTargetHittest) {
1774 RefPtr<IMEContentObserver> contentObserver = mIMEContentObserver;
1775 contentObserver->HandleQueryContentEvent(aEvent);
1776 return;
1777 }
1778
1779 ContentEventHandler handler(mPresContext);
1780 handler.HandleQueryContentEvent(aEvent);
1781}
1782
1783static AccessKeyType GetAccessKeyTypeFor(nsISupports* aDocShell) {
1784 nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(aDocShell));
1785 if (!treeItem) {
1786 return AccessKeyType::eNone;
1787 }
1788
1789 switch (treeItem->ItemType()) {
1790 case nsIDocShellTreeItem::typeChrome:
1791 return AccessKeyType::eChrome;
1792 case nsIDocShellTreeItem::typeContent:
1793 return AccessKeyType::eContent;
1794 default:
1795 return AccessKeyType::eNone;
1796 }
1797}
1798
1799static bool IsAccessKeyTarget(Element* aElement, nsAString& aKey) {
1800 // Use GetAttr because we want Unicode case=insensitive matching
1801 // XXXbz shouldn't this be case-sensitive, per spec?
1802 nsString contentKey;
1803 if (!aElement || !aElement->GetAttr(nsGkAtoms::accesskey, contentKey) ||
1804 !contentKey.Equals(aKey, nsCaseInsensitiveStringComparator)) {
1805 return false;
1806 }
1807
1808 if (!aElement->IsXULElement()) {
1809 return true;
1810 }
1811
1812 // For XUL we do visibility checks.
1813 nsIFrame* frame = aElement->GetPrimaryFrame();
1814 if (!frame) {
1815 return false;
1816 }
1817
1818 if (frame->IsFocusable()) {
1819 return true;
1820 }
1821
1822 if (!frame->IsVisibleConsideringAncestors()) {
1823 return false;
1824 }
1825
1826 // XUL controls can be activated.
1827 nsCOMPtr<nsIDOMXULControlElement> control = aElement->AsXULControl();
1828 if (control) {
1829 return true;
1830 }
1831
1832 // XUL label elements are never focusable, so we need to check for them
1833 // explicitly before giving up.
1834 if (aElement->IsXULElement(nsGkAtoms::label)) {
1835 return true;
1836 }
1837
1838 return false;
1839}
1840
1841bool EventStateManager::CheckIfEventMatchesAccessKey(
1842 WidgetKeyboardEvent* aEvent, nsPresContext* aPresContext) {
1843 AutoTArray<uint32_t, 10> accessCharCodes;
1844 aEvent->GetAccessKeyCandidates(accessCharCodes);
1845 return WalkESMTreeToHandleAccessKey(aEvent, aPresContext, accessCharCodes,
1846 nullptr, eAccessKeyProcessingNormal,
1847 false);
1848}
1849
1850bool EventStateManager::LookForAccessKeyAndExecute(
1851 nsTArray<uint32_t>& aAccessCharCodes, bool aIsTrustedEvent, bool aIsRepeat,
1852 bool aExecute) {
1853 int32_t count, start = -1;
1854 if (Element* focusedElement = GetFocusedElement()) {
1855 start = mAccessKeys.IndexOf(focusedElement);
1856 if (start == -1 && focusedElement->IsInNativeAnonymousSubtree()) {
1857 start = mAccessKeys.IndexOf(Element::FromNodeOrNull(
1858 focusedElement->GetClosestNativeAnonymousSubtreeRootParentOrHost()));
1859 }
1860 }
1861 RefPtr<Element> element;
1862 int32_t length = mAccessKeys.Count();
1863 for (uint32_t i = 0; i < aAccessCharCodes.Length(); ++i) {
1864 uint32_t ch = aAccessCharCodes[i];
1865 nsAutoString accessKey;
1866 AppendUCS4ToUTF16(ch, accessKey);
1867 for (count = 1; count <= length; ++count) {
1868 // mAccessKeys always stores Element instances.
1869 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"
, 1869); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "length == mAccessKeys.Count()"
")"); do { MOZ_CrashSequence(__null, 1869); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1870 element = mAccessKeys[(start + count) % length];
1871 if (IsAccessKeyTarget(element, accessKey)) {
1872 if (!aExecute) {
1873 return true;
1874 }
1875 Document* doc = element->OwnerDoc();
1876 const bool shouldActivate = [&] {
1877 if (!StaticPrefs::accessibility_accesskeycausesactivation()) {
1878 return false;
1879 }
1880 if (aIsRepeat && nsContentUtils::IsChromeDoc(doc)) {
1881 return false;
1882 }
1883
1884 // XXXedgar, Bug 1700646, maybe we could use other data structure to
1885 // make searching target with same accesskey easier, and current setup
1886 // could not ensure we cycle the target with tree order.
1887 int32_t j = 0;
1888 while (++j < length) {
1889 Element* el = mAccessKeys[(start + count + j) % length];
1890 if (IsAccessKeyTarget(el, accessKey)) {
1891 return false;
1892 }
1893 }
1894 return true;
1895 }();
1896
1897 // TODO(bug 1641171): This shouldn't be needed if we considered the
1898 // accesskey combination properly.
1899 if (aIsTrustedEvent) {
1900 doc->NotifyUserGestureActivation();
1901 }
1902
1903 auto result =
1904 element->PerformAccesskey(shouldActivate, aIsTrustedEvent);
1905 if (result.isOk()) {
1906 if (result.unwrap() && aIsTrustedEvent) {
1907 // If this is a child process, inform the parent that we want the
1908 // focus, but pass false since we don't want to change the window
1909 // order.
1910 nsIDocShell* docShell = mPresContext->GetDocShell();
1911 nsCOMPtr<nsIBrowserChild> child =
1912 docShell ? docShell->GetBrowserChild() : nullptr;
1913 if (child) {
1914 child->SendRequestFocus(false, CallerType::System);
1915 }
1916 }
1917 return true;
1918 }
1919 }
1920 }
1921 }
1922 return false;
1923}
1924
1925// static
1926void EventStateManager::GetAccessKeyLabelPrefix(Element* aElement,
1927 nsAString& aPrefix) {
1928 aPrefix.Truncate();
1929 nsAutoString separator, modifierText;
1930 nsContentUtils::GetModifierSeparatorText(separator);
1931
1932 AccessKeyType accessKeyType =
1933 GetAccessKeyTypeFor(aElement->OwnerDoc()->GetDocShell());
1934 if (accessKeyType == AccessKeyType::eNone) {
1935 return;
1936 }
1937 Modifiers modifiers = WidgetKeyboardEvent::AccessKeyModifiers(accessKeyType);
1938 if (modifiers == MODIFIER_NONE) {
1939 return;
1940 }
1941
1942 if (modifiers & MODIFIER_CONTROL) {
1943 nsContentUtils::GetControlText(modifierText);
1944 aPrefix.Append(modifierText + separator);
1945 }
1946 if (modifiers & MODIFIER_META) {
1947 nsContentUtils::GetCommandOrWinText(modifierText);
1948 aPrefix.Append(modifierText + separator);
1949 }
1950 if (modifiers & MODIFIER_ALT) {
1951 nsContentUtils::GetAltText(modifierText);
1952 aPrefix.Append(modifierText + separator);
1953 }
1954 if (modifiers & MODIFIER_SHIFT) {
1955 nsContentUtils::GetShiftText(modifierText);
1956 aPrefix.Append(modifierText + separator);
1957 }
1958}
1959
1960struct MOZ_STACK_CLASS AccessKeyInfo {
1961 WidgetKeyboardEvent* event;
1962 nsTArray<uint32_t>& charCodes;
1963
1964 AccessKeyInfo(WidgetKeyboardEvent* aEvent, nsTArray<uint32_t>& aCharCodes)
1965 : event(aEvent), charCodes(aCharCodes) {}
1966};
1967
1968bool EventStateManager::WalkESMTreeToHandleAccessKey(
1969 WidgetKeyboardEvent* aEvent, nsPresContext* aPresContext,
1970 nsTArray<uint32_t>& aAccessCharCodes, nsIDocShellTreeItem* aBubbledFrom,
1971 ProcessingAccessKeyState aAccessKeyState, bool aExecute) {
1972 EnsureDocument(mPresContext);
1973 nsCOMPtr<nsIDocShell> docShell = aPresContext->GetDocShell();
1974 if (NS_WARN_IF(!docShell)NS_warn_if_impl(!docShell, "!docShell", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1974)
|| NS_WARN_IF(!mDocument)NS_warn_if_impl(!mDocument, "!mDocument", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1974)
) {
1975 return false;
1976 }
1977 AccessKeyType accessKeyType = GetAccessKeyTypeFor(docShell);
1978 if (accessKeyType == AccessKeyType::eNone) {
1979 return false;
1980 }
1981 // Alt or other accesskey modifier is down, we may need to do an accesskey.
1982 if (mAccessKeys.Count() > 0 &&
1983 aEvent->ModifiersMatchWithAccessKey(accessKeyType)) {
1984 // Someone registered an accesskey. Find and activate it.
1985 if (LookForAccessKeyAndExecute(aAccessCharCodes, aEvent->IsTrusted(),
1986 aEvent->mIsRepeat, aExecute)) {
1987 return true;
1988 }
1989 }
1990
1991 int32_t childCount;
1992 docShell->GetInProcessChildCount(&childCount);
1993 for (int32_t counter = 0; counter < childCount; counter++) {
1994 // Not processing the child which bubbles up the handling
1995 nsCOMPtr<nsIDocShellTreeItem> subShellItem;
1996 docShell->GetInProcessChildAt(counter, getter_AddRefs(subShellItem));
1997 if (aAccessKeyState == eAccessKeyProcessingUp &&
1998 subShellItem == aBubbledFrom) {
1999 continue;
2000 }
2001
2002 nsCOMPtr<nsIDocShell> subDS = do_QueryInterface(subShellItem);
2003 if (subDS && IsShellVisible(subDS)) {
2004 // Guarantee subPresShell lifetime while we're handling access key
2005 // since somebody may assume that it won't be deleted before the
2006 // corresponding nsPresContext and EventStateManager.
2007 RefPtr<PresShell> subPresShell = subDS->GetPresShell();
2008
2009 // Docshells need not have a presshell (eg. display:none
2010 // iframes, docshells in transition between documents, etc).
2011 if (!subPresShell) {
2012 // Oh, well. Just move on to the next child
2013 continue;
2014 }
2015
2016 RefPtr<nsPresContext> subPresContext = subPresShell->GetPresContext();
2017
2018 RefPtr<EventStateManager> esm =
2019 static_cast<EventStateManager*>(subPresContext->EventStateManager());
2020
2021 if (esm && esm->WalkESMTreeToHandleAccessKey(
2022 aEvent, subPresContext, aAccessCharCodes, nullptr,
2023 eAccessKeyProcessingDown, aExecute)) {
2024 return true;
2025 }
2026 }
2027 } // if end . checking all sub docshell ends here.
2028
2029 // bubble up the process to the parent docshell if necessary
2030 if (eAccessKeyProcessingDown != aAccessKeyState) {
2031 nsCOMPtr<nsIDocShellTreeItem> parentShellItem;
2032 docShell->GetInProcessParent(getter_AddRefs(parentShellItem));
2033 nsCOMPtr<nsIDocShell> parentDS = do_QueryInterface(parentShellItem);
2034 if (parentDS) {
2035 // Guarantee parentPresShell lifetime while we're handling access key
2036 // since somebody may assume that it won't be deleted before the
2037 // corresponding nsPresContext and EventStateManager.
2038 RefPtr<PresShell> parentPresShell = parentDS->GetPresShell();
2039 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", 2040
); MOZ_PretendNoReturn(); } } while (0)
2040 "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", 2040
); MOZ_PretendNoReturn(); } } while (0)
;
2041
2042 RefPtr<nsPresContext> parentPresContext =
2043 parentPresShell->GetPresContext();
2044 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"
, 2044); MOZ_PretendNoReturn(); } } while (0)
;
2045
2046 RefPtr<EventStateManager> esm = static_cast<EventStateManager*>(
2047 parentPresContext->EventStateManager());
2048 if (esm && esm->WalkESMTreeToHandleAccessKey(
2049 aEvent, parentPresContext, aAccessCharCodes, docShell,
2050 eAccessKeyProcessingDown, aExecute)) {
2051 return true;
2052 }
2053 }
2054 } // if end. bubble up process
2055
2056 // If the content access key modifier is pressed, try remote children
2057 if (aExecute &&
2058 aEvent->ModifiersMatchWithAccessKey(AccessKeyType::eContent) &&
2059 mDocument && mDocument->GetWindow()) {
2060 // If the focus is currently on a node with a BrowserParent, the key event
2061 // should've gotten forwarded to the child process and HandleAccessKey
2062 // called from there.
2063 if (BrowserParent::GetFrom(GetFocusedElement())) {
2064 // If access key may be only in remote contents, this method won't handle
2065 // access key synchronously. In this case, only reply event should reach
2066 // here.
2067 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", 2068
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->IsHandledInRemoteProcess() || !aEvent->IsWaitingReplyFromRemoteProcess()"
")"); do { MOZ_CrashSequence(__null, 2068); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2068 !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", 2068
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->IsHandledInRemoteProcess() || !aEvent->IsWaitingReplyFromRemoteProcess()"
")"); do { MOZ_CrashSequence(__null, 2068); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2069 }
2070 // If focus is somewhere else, then we need to check the remote children.
2071 // However, if the event has already been handled in a remote process,
2072 // then, focus is moved from the remote process after posting the event.
2073 // In such case, we shouldn't retry to handle access keys in remote
2074 // processes.
2075 else if (!aEvent->IsHandledInRemoteProcess()) {
2076 AccessKeyInfo accessKeyInfo(aEvent, aAccessCharCodes);
2077 nsContentUtils::CallOnAllRemoteChildren(
2078 mDocument->GetWindow(),
2079 [&accessKeyInfo](BrowserParent* aBrowserParent) -> CallState {
2080 // Only forward accesskeys for the active tab.
2081 if (aBrowserParent->GetDocShellIsActive()) {
2082 // Even if there is no target for the accesskey in this process,
2083 // the event may match with a content accesskey. If so, the
2084 // keyboard event should be handled with reply event for
2085 // preventing double action. (e.g., Alt+Shift+F on Windows may
2086 // focus a content in remote and open "File" menu.)
2087 accessKeyInfo.event->StopPropagation();
2088 accessKeyInfo.event->MarkAsWaitingReplyFromRemoteProcess();
2089 aBrowserParent->HandleAccessKey(*accessKeyInfo.event,
2090 accessKeyInfo.charCodes);
2091 return CallState::Stop;
2092 }
2093
2094 return CallState::Continue;
2095 });
2096 }
2097 }
2098
2099 return false;
2100} // end of HandleAccessKey
2101
2102static BrowserParent* GetBrowserParentAncestor(BrowserParent* aBrowserParent) {
2103 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", 2103
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowserParent" ")"
); do { MOZ_CrashSequence(__null, 2103); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2104
2105 BrowserBridgeParent* bbp = aBrowserParent->GetBrowserBridgeParent();
2106 if (!bbp) {
2107 return nullptr;
2108 }
2109
2110 return bbp->Manager();
2111}
2112
2113static void DispatchCrossProcessMouseExitEvents(WidgetMouseEvent* aMouseEvent,
2114 BrowserParent* aRemoteTarget,
2115 BrowserParent* aStopAncestor,
2116 bool aIsReallyExit) {
2117 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"
, 2117); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseEvent"
")"); do { MOZ_CrashSequence(__null, 2117); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2118 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", 2118
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRemoteTarget" ")"
); do { MOZ_CrashSequence(__null, 2118); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2119 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"
, 2119); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRemoteTarget != aStopAncestor"
")"); do { MOZ_CrashSequence(__null, 2119); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2120 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", 2121
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::GetCommonBrowserParentAncestor( aRemoteTarget, aStopAncestor)"
")"); do { MOZ_CrashSequence(__null, 2121); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2121 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", 2121
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::GetCommonBrowserParentAncestor( aRemoteTarget, aStopAncestor)"
")"); do { MOZ_CrashSequence(__null, 2121); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2122
2123 while (aRemoteTarget != aStopAncestor) {
2124 UniquePtr<WidgetMouseEvent> mouseExitEvent =
2125 CreateMouseOrPointerWidgetEvent(aMouseEvent, eMouseExitFromWidget,
2126 aMouseEvent->mRelatedTarget);
2127 mouseExitEvent->mExitFrom =
2128 Some(aIsReallyExit ? WidgetMouseEvent::ePuppet
2129 : WidgetMouseEvent::ePuppetParentToPuppetChild);
2130
2131 auto ContentReactsToPointerEvents = [](BrowserParent* aRemoteTarget) {
2132 if (Element* owner = aRemoteTarget->GetOwnerElement()) {
2133 if (nsSubDocumentFrame* subDocFrame =
2134 do_QueryFrame(owner->GetPrimaryFrame())) {
2135 return subDocFrame->ContentReactsToPointerEvents();
2136 }
2137 }
2138 return true;
2139 };
2140
2141 if (ContentReactsToPointerEvents(aRemoteTarget)) {
2142 aRemoteTarget->SendRealMouseEvent(*mouseExitEvent);
2143 }
2144
2145 aRemoteTarget = GetBrowserParentAncestor(aRemoteTarget);
2146 }
2147}
2148
2149void EventStateManager::DispatchCrossProcessEvent(WidgetEvent* aEvent,
2150 BrowserParent* aRemoteTarget,
2151 nsEventStatus* aStatus) {
2152 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"
, 2152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 2152); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2153 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", 2153
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRemoteTarget" ")"
); do { MOZ_CrashSequence(__null, 2153); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2154 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"
, 2154); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 2154); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2155
2156 BrowserParent* remote = aRemoteTarget;
2157
2158 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
2159 bool isContextMenuKey = mouseEvent && mouseEvent->IsContextMenuKeyEvent();
2160 if (aEvent->mClass == eKeyboardEventClass || isContextMenuKey) {
2161 // APZ attaches a LayersId to hit-testable events, for keyboard events,
2162 // we use focus.
2163 BrowserParent* preciseRemote = BrowserParent::GetFocused();
2164 if (preciseRemote) {
2165 remote = preciseRemote;
2166 }
2167 // else there is a race between layout and focus tracking,
2168 // so fall back to delivering the event to the topmost child process.
2169 } else if (aEvent->mLayersId.IsValid()) {
2170 BrowserParent* preciseRemote =
2171 BrowserParent::GetBrowserParentFromLayersId(aEvent->mLayersId);
2172 if (preciseRemote) {
2173 remote = preciseRemote;
2174 }
2175 // else there is a race between APZ and the LayersId to BrowserParent
2176 // mapping, so fall back to delivering the event to the topmost child
2177 // process.
2178 }
2179
2180 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"
, 2180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage != ePointerClick"
")"); do { MOZ_CrashSequence(__null, 2180); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2181 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", 2181
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage != ePointerAuxClick"
")"); do { MOZ_CrashSequence(__null, 2181); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2182
2183 // SendReal* will transform the coordinate to the child process coordinate
2184 // space. So restore the coordinate after the event has been dispatched to the
2185 // child process to avoid using the transformed coordinate afterward.
2186 AutoRestore<LayoutDeviceIntPoint> restore(aEvent->mRefPoint);
2187 switch (aEvent->mClass) {
2188 case ePointerEventClass:
2189 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"
, 2189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eContextMenu"
")"); do { MOZ_CrashSequence(__null, 2189); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2190 [[fallthrough]];
2191 case eMouseEventClass: {
2192 BrowserParent* oldRemote = BrowserParent::GetLastMouseRemoteTarget();
2193
2194 // If this is a eMouseExitFromWidget event, need to redirect the event to
2195 // the last remote and and notify all its ancestors about the exit, if
2196 // any.
2197 if (mouseEvent->mMessage == eMouseExitFromWidget) {
2198 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", 2198
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet"
")"); do { MOZ_CrashSequence(__null, 2198); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2199 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", 2199
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mReason == WidgetMouseEvent::eReal"
")"); do { MOZ_CrashSequence(__null, 2199); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2200 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"
, 2200); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mouseEvent->mLayersId.IsValid()"
")"); do { MOZ_CrashSequence(__null, 2200); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2201 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", 2201
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "remote->GetBrowserHost()"
")"); do { MOZ_CrashSequence(__null, 2201); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2202
2203 if (oldRemote && oldRemote != remote) {
2204 (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", 2205
)
2205 remote, oldRemote) != remote)NS_warn_if_impl(nsContentUtils::GetCommonBrowserParentAncestor
( remote, oldRemote) != remote, "nsContentUtils::GetCommonBrowserParentAncestor( remote, oldRemote) != remote"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2205
)
;
2206 remote = oldRemote;
2207 }
2208
2209 DispatchCrossProcessMouseExitEvents(mouseEvent, remote, nullptr, true);
2210 return;
2211 }
2212
2213 if (BrowserParent* pointerLockedRemote =
2214 PointerLockManager::GetLockedRemoteTarget()) {
2215 remote = pointerLockedRemote;
2216 } else if (BrowserParent* pointerCapturedRemote =
2217 PointerEventHandler::GetPointerCapturingRemoteTarget(
2218 mouseEvent->pointerId)) {
2219 remote = pointerCapturedRemote;
2220 } else if (BrowserParent* capturingRemote =
2221 PresShell::GetCapturingRemoteTarget()) {
2222 remote = capturingRemote;
2223 }
2224
2225 // If a mouse is over a remote target A, and then moves to
2226 // remote target B, we'd deliver the event directly to remote target B
2227 // after the moving, A would never get notified that the mouse left.
2228 // So we generate a exit event to notify A after the move.
2229 // XXXedgar, if the synthesized mouse events could deliver to the correct
2230 // process directly (see
2231 // https://bugzilla.mozilla.org/show_bug.cgi?id=1549355), we probably
2232 // don't need to check mReason then.
2233 if (mouseEvent->mReason == WidgetMouseEvent::eReal &&
2234 remote != oldRemote) {
2235 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", 2235
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mMessage != eMouseExitFromWidget"
")"); do { MOZ_CrashSequence(__null, 2235); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2236 if (oldRemote) {
2237 BrowserParent* commonAncestor =
2238 nsContentUtils::GetCommonBrowserParentAncestor(remote, oldRemote);
2239 if (commonAncestor == oldRemote) {
2240 // Mouse moves to the inner OOP frame, it is not a really exit.
2241 DispatchCrossProcessMouseExitEvents(
2242 mouseEvent, GetBrowserParentAncestor(remote),
2243 GetBrowserParentAncestor(commonAncestor), false);
2244 } else if (commonAncestor == remote) {
2245 // Mouse moves to the outer OOP frame, it is a really exit.
2246 DispatchCrossProcessMouseExitEvents(mouseEvent, oldRemote,
2247 commonAncestor, true);
2248 } else {
2249 // Mouse moves to OOP frame in other subtree, it is a really exit,
2250 // need to notify all its ancestors before common ancestor about the
2251 // exit.
2252 DispatchCrossProcessMouseExitEvents(mouseEvent, oldRemote,
2253 commonAncestor, true);
2254 if (commonAncestor) {
2255 UniquePtr<WidgetMouseEvent> mouseExitEvent =
2256 CreateMouseOrPointerWidgetEvent(mouseEvent,
2257 eMouseExitFromWidget,
2258 mouseEvent->mRelatedTarget);
2259 mouseExitEvent->mExitFrom =
2260 Some(WidgetMouseEvent::ePuppetParentToPuppetChild);
2261 commonAncestor->SendRealMouseEvent(*mouseExitEvent);
2262 }
2263 }
2264 }
2265
2266 if (mouseEvent->mMessage != eMouseExitFromWidget &&
2267 mouseEvent->mMessage != eMouseEnterIntoWidget) {
2268 // This is to make cursor would be updated correctly.
2269 remote->MouseEnterIntoWidget();
2270 }
2271 }
2272
2273 remote->SendRealMouseEvent(*mouseEvent);
2274 return;
2275 }
2276 case eKeyboardEventClass: {
2277 auto* keyboardEvent = aEvent->AsKeyboardEvent();
2278 if (aEvent->mMessage == eKeyUp) {
2279 HandleKeyUpInteraction(keyboardEvent);
2280 }
2281 remote->SendRealKeyEvent(*keyboardEvent);
2282 return;
2283 }
2284 case eWheelEventClass: {
2285 if (BrowserParent* pointerLockedRemote =
2286 PointerLockManager::GetLockedRemoteTarget()) {
2287 remote = pointerLockedRemote;
2288 }
2289 remote->SendMouseWheelEvent(*aEvent->AsWheelEvent());
2290 return;
2291 }
2292 case eTouchEventClass: {
2293 // Let the child process synthesize a mouse event if needed, and
2294 // ensure we don't synthesize one in this process.
2295 *aStatus = nsEventStatus_eConsumeNoDefault;
2296 remote->SendRealTouchEvent(*aEvent->AsTouchEvent());
2297 return;
2298 }
2299 case eDragEventClass: {
2300 RefPtr<BrowserParent> browserParent = remote;
2301 browserParent->MaybeInvokeDragSession(aEvent->mMessage);
2302
2303 RefPtr<nsIWidget> widget = browserParent->GetTopLevelWidget();
2304 nsCOMPtr<nsIDragSession> dragSession =
2305 nsContentUtils::GetDragSession(widget);
2306 uint32_t dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
2307 uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE;
2308 nsCOMPtr<nsIPrincipal> principal;
2309 nsCOMPtr<nsIPolicyContainer> policyContainer;
2310
2311 if (dragSession) {
2312 dragSession->DragEventDispatchedToChildProcess();
2313 dragSession->GetDragAction(&action);
2314 dragSession->GetTriggeringPrincipal(getter_AddRefs(principal));
2315 dragSession->GetPolicyContainer(getter_AddRefs(policyContainer));
2316 RefPtr<DataTransfer> initialDataTransfer =
2317 dragSession->GetDataTransfer();
2318 if (initialDataTransfer) {
2319 dropEffect = initialDataTransfer->DropEffectInt();
2320 }
2321 }
2322
2323 browserParent->SendRealDragEvent(*aEvent->AsDragEvent(), action,
2324 dropEffect, principal, policyContainer);
2325 return;
2326 }
2327 default: {
2328 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", 2328
); AnnotateMozCrashReason("MOZ_CRASH(" "Attempt to send non-whitelisted event?"
")"); do { MOZ_CrashSequence(__null, 2328); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2329 }
2330 }
2331}
2332
2333bool EventStateManager::IsRemoteTarget(nsIContent* target) {
2334 return BrowserParent::GetFrom(target) || BrowserBridgeChild::GetFrom(target);
2335}
2336
2337bool EventStateManager::IsTopLevelRemoteTarget(nsIContent* target) {
2338 return !!BrowserParent::GetFrom(target);
2339}
2340
2341bool EventStateManager::HandleCrossProcessEvent(WidgetEvent* aEvent,
2342 nsEventStatus* aStatus) {
2343 if (!aEvent->CanBeSentToRemoteProcess()) {
2344 return false;
2345 }
2346
2347 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",
2348); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEvent->HasBeenPostedToRemoteProcess()"
") (" "Why do we need to post same event to remote processes again?"
")"); do { MOZ_CrashSequence(__null, 2348); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2348 "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",
2348); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEvent->HasBeenPostedToRemoteProcess()"
") (" "Why do we need to post same event to remote processes again?"
")"); do { MOZ_CrashSequence(__null, 2348); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2349
2350 // Collect the remote event targets we're going to forward this
2351 // event to.
2352 //
2353 // NB: the elements of |remoteTargets| must be unique, for correctness.
2354 AutoTArray<RefPtr<BrowserParent>, 1> remoteTargets;
2355 if (aEvent->mClass != eTouchEventClass || aEvent->mMessage == eTouchStart) {
2356 // If this event only has one target, and it's remote, add it to
2357 // the array.
2358 nsIFrame* frame = aEvent->mMessage == eDragExit
2359 ? sLastDragOverFrame.GetFrame()
2360 : GetEventTarget();
2361 nsIContent* target = frame ? frame->GetContent() : nullptr;
2362 if (BrowserParent* remoteTarget = BrowserParent::GetFrom(target)) {
2363 remoteTargets.AppendElement(remoteTarget);
2364 }
2365 } else {
2366 // This is a touch event with possibly multiple touch points.
2367 // Each touch point may have its own target. So iterate through
2368 // all of them and collect the unique set of targets for event
2369 // forwarding.
2370 //
2371 // This loop is similar to the one used in
2372 // PresShell::DispatchTouchEvent().
2373 const WidgetTouchEvent::TouchArray& touches =
2374 aEvent->AsTouchEvent()->mTouches;
2375 for (uint32_t i = 0; i < touches.Length(); ++i) {
2376 Touch* touch = touches[i];
2377 // NB: the |mChanged| check is an optimization, subprocesses can
2378 // compute this for themselves. If the touch hasn't changed, we
2379 // may be able to avoid forwarding the event entirely (which is
2380 // not free).
2381 if (!touch || !touch->mChanged) {
2382 continue;
2383 }
2384 nsCOMPtr<EventTarget> targetPtr = touch->mTarget;
2385 if (!targetPtr) {
2386 continue;
2387 }
2388 nsCOMPtr<nsIContent> target = do_QueryInterface(targetPtr);
2389 BrowserParent* remoteTarget = BrowserParent::GetFrom(target);
2390 if (remoteTarget && !remoteTargets.Contains(remoteTarget)) {
2391 remoteTargets.AppendElement(remoteTarget);
2392 }
2393 }
2394 }
2395
2396 if (remoteTargets.Length() == 0) {
2397 return false;
2398 }
2399
2400 // Dispatch the event to the remote target.
2401 for (uint32_t i = 0; i < remoteTargets.Length(); ++i) {
2402 DispatchCrossProcessEvent(aEvent, remoteTargets[i], aStatus);
2403 }
2404 return aEvent->HasBeenPostedToRemoteProcess();
2405}
2406
2407//
2408// CreateClickHoldTimer
2409//
2410// Fire off a timer for determining if the user wants click-hold. This timer
2411// is a one-shot that will be cancelled when the user moves enough to fire
2412// a drag.
2413//
2414void EventStateManager::CreateClickHoldTimer(nsPresContext* inPresContext,
2415 nsIFrame* inDownFrame,
2416 WidgetGUIEvent* inMouseDownEvent) {
2417 if (!inMouseDownEvent->IsTrusted() ||
2418 IsTopLevelRemoteTarget(mGestureDownContent) ||
2419 PointerLockManager::IsLocked()) {
2420 return;
2421 }
2422
2423 // just to be anal (er, safe)
2424 if (mClickHoldTimer) {
2425 mClickHoldTimer->Cancel();
2426 mClickHoldTimer = nullptr;
2427 }
2428
2429 // if content clicked on has a popup, don't even start the timer
2430 // since we'll end up conflicting and both will show.
2431 if (mGestureDownContent &&
2432 nsContentUtils::HasNonEmptyAttr(mGestureDownContent, kNameSpaceID_None,
2433 nsGkAtoms::popup)) {
2434 return;
2435 }
2436
2437 int32_t clickHoldDelay = StaticPrefs::ui_click_hold_context_menus_delay();
2438 NS_NewTimerWithFuncCallback(
2439 getter_AddRefs(mClickHoldTimer), sClickHoldCallback, this, clickHoldDelay,
2440 nsITimer::TYPE_ONE_SHOT, "EventStateManager::CreateClickHoldTimer"_ns);
2441} // CreateClickHoldTimer
2442
2443//
2444// KillClickHoldTimer
2445//
2446// Stop the timer that would show the context menu dead in its tracks
2447//
2448void EventStateManager::KillClickHoldTimer() {
2449 if (mClickHoldTimer) {
2450 mClickHoldTimer->Cancel();
2451 mClickHoldTimer = nullptr;
2452 }
2453}
2454
2455//
2456// sClickHoldCallback
2457//
2458// This fires after the mouse has been down for a certain length of time.
2459//
2460void EventStateManager::sClickHoldCallback(nsITimer* aTimer, void* aESM) {
2461 RefPtr<EventStateManager> self = static_cast<EventStateManager*>(aESM);
2462 if (self) {
2463 self->FireContextClick();
2464 }
2465
2466 // NOTE: |aTimer| and |self->mAutoHideTimer| are invalid after calling
2467 // ClosePopup();
2468
2469} // sAutoHideCallback
2470
2471//
2472// FireContextClick
2473//
2474// If we're this far, our timer has fired, which means the mouse has been down
2475// for a certain period of time and has not moved enough to generate a
2476// dragGesture. We can be certain the user wants a context-click at this stage,
2477// so generate a dom event and fire it in.
2478//
2479// After the event fires, check if PreventDefault() has been set on the event
2480// which means that someone either ate the event or put up a context menu. This
2481// is our cue to stop tracking the drag gesture. If we always did this,
2482// draggable items w/out a context menu wouldn't be draggable after a certain
2483// length of time, which is _not_ what we want.
2484//
2485void EventStateManager::FireContextClick() {
2486 if (!mGestureDownContent || !mPresContext || PointerLockManager::IsLocked()) {
2487 return;
2488 }
2489
2490#ifdef XP_MACOSX
2491 // Hack to ensure that we don't show a context menu when the user
2492 // let go of the mouse after a long cpu-hogging operation prevented
2493 // us from handling any OS events. See bug 117589.
2494 if (!CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
2495 kCGMouseButtonLeft))
2496 return;
2497#endif
2498
2499 nsEventStatus status = nsEventStatus_eIgnore;
2500
2501 // Dispatch to the DOM. We have to fake out the ESM and tell it that the
2502 // current target frame is actually where the mouseDown occurred, otherwise it
2503 // will use the frame the mouse is currently over which may or may not be
2504 // the same. (Note: saari and I have decided that we don't have to reset
2505 // |mCurrentTarget| when we're through because no one else is doing anything
2506 // more with this event and it will get reset on the very next event to the
2507 // correct frame).
2508 mCurrentTarget = mPresContext->GetPrimaryFrameFor(mGestureDownContent);
2509 // make sure the widget sticks around
2510 nsCOMPtr<nsIWidget> targetWidget;
2511 if (mCurrentTarget && (targetWidget = mCurrentTarget->GetNearestWidget())) {
2512 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"
, 2514); MOZ_PretendNoReturn(); } } while (0)
2513 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"
, 2514); MOZ_PretendNoReturn(); } } while (0)
2514 "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"
, 2514); MOZ_PretendNoReturn(); } } while (0)
;
2515
2516 // before dispatching, check that we're not on something that
2517 // doesn't get a context menu
2518 bool allowedToDispatch = true;
2519
2520 if (mGestureDownContent->IsAnyOfXULElements(nsGkAtoms::scrollbar,
2521 nsGkAtoms::scrollbarbutton,
2522 nsGkAtoms::button)) {
2523 allowedToDispatch = false;
2524 } else if (mGestureDownContent->IsXULElement(nsGkAtoms::toolbarbutton)) {
2525 // a <toolbarbutton> that has the container attribute set
2526 // will already have its own dropdown.
2527 if (nsContentUtils::HasNonEmptyAttr(
2528 mGestureDownContent, kNameSpaceID_None, nsGkAtoms::container)) {
2529 allowedToDispatch = false;
2530 } else {
2531 // If the toolbar button has an open menu, don't attempt to open
2532 // a second menu
2533 if (mGestureDownContent->IsElement() &&
2534 mGestureDownContent->AsElement()->AttrValueIs(
2535 kNameSpaceID_None, nsGkAtoms::open, nsGkAtoms::_true,
2536 eCaseMatters)) {
2537 allowedToDispatch = false;
2538 }
2539 }
2540 } else if (mGestureDownContent->IsHTMLElement()) {
2541 if (const auto* formCtrl =
2542 nsIFormControl::FromNode(mGestureDownContent)) {
2543 allowedToDispatch =
2544 formCtrl->IsTextControl(/*aExcludePassword*/ false) ||
2545 formCtrl->ControlType() == FormControlType::InputFile;
2546 } else if (mGestureDownContent->IsAnyOfHTMLElements(
2547 nsGkAtoms::embed, nsGkAtoms::object, nsGkAtoms::label)) {
2548 allowedToDispatch = false;
2549 }
2550 }
2551
2552 if (allowedToDispatch) {
2553 // init the event while mCurrentTarget is still good
2554 WidgetPointerEvent event(true, eContextMenu, targetWidget);
2555 event.mClickCount = 1;
2556 FillInEventFromGestureDown(&event);
2557
2558 // we need to forget the clicking content and click count for the
2559 // following eMouseUp event when click-holding context menus
2560 GetLastMouseButtonPressInfo(event.mButton).Clear();
2561
2562 // stop selection tracking, we're in control now
2563 if (mCurrentTarget) {
2564 RefPtr<nsFrameSelection> frameSel = mCurrentTarget->GetFrameSelection();
2565
2566 if (frameSel && frameSel->GetDragState()) {
2567 // note that this can cause selection changed events to fire if we're
2568 // in a text field, which will null out mCurrentTarget
2569 frameSel->SetDragState(false);
2570 }
2571 }
2572
2573 AutoHandlingUserInputStatePusher userInpStatePusher(true, &event);
2574
2575 // dispatch to DOM
2576 RefPtr<nsPresContext> presContext = mPresContext;
2577
2578 // The contextmenu event handled by PresShell will apply to elements (not
2579 // all nodes) correctly and will be dispatched to EventStateManager for
2580 // further handling preventing click event and stopping tracking drag
2581 // gesture.
2582 if (RefPtr<PresShell> presShell = presContext->GetPresShell()) {
2583 presShell->HandleEvent(mCurrentTarget, &event, false, &status);
2584 }
2585
2586 // We don't need to dispatch to frame handling because no frames
2587 // watch eContextMenu except for nsMenuFrame and that's only for
2588 // dismissal. That's just as well since we don't really know
2589 // which frame to send it to.
2590 }
2591 }
2592
2593 // stop tracking a drag whatever the event has been handled or not.
2594 StopTrackingDragGesture(true);
2595
2596 KillClickHoldTimer();
2597
2598} // FireContextClick
2599
2600//
2601// BeginTrackingDragGesture
2602//
2603// Record that the mouse has gone down and that we should move to TRACKING state
2604// of d&d gesture tracker.
2605//
2606// We also use this to track click-hold context menus. When the mouse goes down,
2607// fire off a short timer. If the timer goes off and we have yet to fire the
2608// drag gesture (ie, the mouse hasn't moved a certain distance), then we can
2609// assume the user wants a click-hold, so fire a context-click event. We only
2610// want to cancel the drag gesture if the context-click event is handled.
2611//
2612void EventStateManager::BeginTrackingDragGesture(
2613 nsPresContext* aPresContext, WidgetMouseEvent& aMouseDownOrTouchDragEvent,
2614 nsIFrame* aMouseDownOrTouchDragFrame) {
2615 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", 2616
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseDownOrTouchDragEvent.mMessage == eMouseDown || aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag"
")"); do { MOZ_CrashSequence(__null, 2616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2616 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", 2616
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseDownOrTouchDragEvent.mMessage == eMouseDown || aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag"
")"); do { MOZ_CrashSequence(__null, 2616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2617 if (!aMouseDownOrTouchDragEvent.mWidget) [[unlikely]] {
2618 return;
2619 }
2620
2621 // Note that |inDownEvent| could be either a mouse down event or a
2622 // synthesized mouse move event.
2623 SetGestureDownPoint(aMouseDownOrTouchDragEvent);
2624
2625 if (aMouseDownOrTouchDragFrame) {
2626 // We need to store the explicit target of the drag gesture start content,
2627 // i.e., it may be a `Text` even though the event target should be its
2628 // flattened tree parent element because we want to maintain `Selection`
2629 // with the `Text`. E.g., we want to allow to extending selection in a
2630 // draggable editing host, check whether the `Text` is selectable or not
2631 // like in a `Text` of a <button>.
2632 mGestureDownContent =
2633 aMouseDownOrTouchDragFrame->GetExplicitEventTargetContent(
2634 aMouseDownOrTouchDragEvent);
2635 mGestureDownFrameOwner = aMouseDownOrTouchDragFrame->GetContent();
2636 if (!mGestureDownFrameOwner) {
2637 mGestureDownFrameOwner = mGestureDownContent;
2638 }
2639 }
2640 mGestureModifiers = aMouseDownOrTouchDragEvent.mModifiers;
2641 mGestureDownButtons = aMouseDownOrTouchDragEvent.mButtons;
2642 mGestureDownButton = aMouseDownOrTouchDragEvent.mButton;
2643
2644 if (aMouseDownOrTouchDragEvent.mMessage != eMouseTouchDrag &&
2645 StaticPrefs::ui_click_hold_context_menus()) {
2646 // fire off a timer to track click-hold
2647 CreateClickHoldTimer(aPresContext, aMouseDownOrTouchDragFrame,
2648 &aMouseDownOrTouchDragEvent);
2649 }
2650}
2651
2652void EventStateManager::SetGestureDownPoint(const WidgetGUIEvent& aEvent) {
2653 mGestureDownPoint =
2654 GetEventRefPoint(aEvent) + aEvent.mWidget->WidgetToScreenOffset();
2655}
2656
2657LayoutDeviceIntPoint EventStateManager::GetEventRefPoint(
2658 const WidgetEvent& aEvent) const {
2659 const auto* touchEvent = aEvent.AsTouchEvent();
2660 return (touchEvent && !touchEvent->mTouches.IsEmpty())
2661 ? aEvent.AsTouchEvent()->mTouches[0]->mRefPoint
2662 : aEvent.mRefPoint;
2663}
2664
2665void EventStateManager::BeginTrackingRemoteDragGesture(
2666 nsIContent* aContent, RemoteDragStartData* aDragStartData) {
2667 UpdateGestureContent(aContent);
2668 mGestureDownDragStartData = aDragStartData;
2669}
2670
2671//
2672// StopTrackingDragGesture
2673//
2674// Record that the mouse has gone back up so that we should leave the TRACKING
2675// state of d&d gesture tracker and return to the START state.
2676//
2677void EventStateManager::StopTrackingDragGesture(bool aClearInChildProcesses) {
2678 mGestureDownContent = nullptr;
2679 mGestureDownFrameOwner = nullptr;
2680 mGestureDownDragStartData = nullptr;
2681
2682 // If a content process starts a drag but the mouse is released before the
2683 // parent starts the actual drag, the content process will think a drag is
2684 // still happening. Inform any child processes with active drags that the drag
2685 // should be stopped.
2686 if (!aClearInChildProcesses || !XRE_IsParentProcess()) {
2687 return;
2688 }
2689
2690 // Only notify if there is NOT a drag session active in the parent.
2691 RefPtr<nsIDragSession> dragSession =
2692 nsContentUtils::GetDragSession(mPresContext);
2693 if (dragSession) {
2694 return;
2695 }
2696 nsCOMPtr<nsIDragService> dragService =
2697 do_GetService("@mozilla.org/widget/dragservice;1");
2698 if (!dragService) {
2699 return;
2700 }
2701 dragService->RemoveAllBrowsers();
2702}
2703
2704void EventStateManager::FillInEventFromGestureDown(WidgetMouseEvent* aEvent) {
2705 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", 2706
); MOZ_PretendNoReturn(); } } while (0)
2706 "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", 2706
); MOZ_PretendNoReturn(); } } while (0)
;
2707
2708 // Set the coordinates in the new event to the coordinates of
2709 // the old event, adjusted for the fact that the widget might be
2710 // different
2711 aEvent->mRefPoint =
2712 mGestureDownPoint - aEvent->mWidget->WidgetToScreenOffset();
2713 aEvent->mModifiers = mGestureModifiers;
2714 aEvent->mButtons = mGestureDownButtons;
2715 if (aEvent->mMessage == eContextMenu) {
2716 aEvent->mButton = mGestureDownButton;
2717 }
2718}
2719
2720void EventStateManager::MaybeDispatchPointerCancel(
2721 const WidgetInputEvent& aSourceEvent, nsIContent& aTargetContent) {
2722 // Dispatching ePointerCancel clears out mCurrentTarget, which may be used in
2723 // the caller GenerateDragGesture. We have to restore mCurrentTarget.
2724 AutoWeakFrame targetFrame = mCurrentTarget;
2725 const auto restoreCurrentTarget =
2726 MakeScopeExit([&]() { mCurrentTarget = targetFrame; });
2727
2728 const RefPtr<Element> targetElement =
2729 aTargetContent.GetAsElementOrParentElement();
2730 // XXX If there is no proper event target, should we retarget ePointerCancel
2731 // somewhere else?
2732 if (NS_WARN_IF(!targetElement)NS_warn_if_impl(!targetElement, "!targetElement", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2732)
) {
2733 return;
2734 }
2735
2736 if (const WidgetMouseEvent* const mouseEvent = aSourceEvent.AsMouseEvent()) {
2737 PointerEventHandler::DispatchPointerEventWithTarget(
2738 ePointerCancel, *mouseEvent, AutoWeakFrame{}, targetElement);
2739 } else if (const WidgetTouchEvent* const touchEvent =
2740 aSourceEvent.AsTouchEvent()) {
2741 PointerEventHandler::DispatchPointerEventWithTarget(
2742 ePointerCancel, *touchEvent, 0, AutoWeakFrame{}, targetElement);
2743 } else {
2744 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"
, 2746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "MaybeDispatchPointerCancel() should be called with a mouse event or a "
"touch event" ")"); do { MOZ_CrashSequence(__null, 2746); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2745 "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"
, 2746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "MaybeDispatchPointerCancel() should be called with a mouse event or a "
"touch event" ")"); do { MOZ_CrashSequence(__null, 2746); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2746 "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"
, 2746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "MaybeDispatchPointerCancel() should be called with a mouse event or a "
"touch event" ")"); do { MOZ_CrashSequence(__null, 2746); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
2747 }
2748}
2749
2750bool EventStateManager::IsEventOutsideDragThreshold(
2751 const WidgetInputEvent& aEvent) const {
2752 static int32_t sPixelThresholdX = 0;
2753 static int32_t sPixelThresholdY = 0;
2754
2755 if (!sPixelThresholdX) {
2756 sPixelThresholdX =
2757 LookAndFeel::GetInt(LookAndFeel::IntID::DragThresholdX, 0);
2758 sPixelThresholdY =
2759 LookAndFeel::GetInt(LookAndFeel::IntID::DragThresholdY, 0);
2760 if (sPixelThresholdX <= 0) {
2761 sPixelThresholdX = 5;
2762 }
2763 if (sPixelThresholdY <= 0) {
2764 sPixelThresholdY = 5;
2765 }
2766 }
2767
2768 LayoutDeviceIntPoint pt =
2769 aEvent.mWidget->WidgetToScreenOffset() + GetEventRefPoint(aEvent);
2770 LayoutDeviceIntPoint distance = pt - mGestureDownPoint;
2771 return Abs(distance.x) > sPixelThresholdX ||
2772 Abs(distance.y) > sPixelThresholdY;
2773}
2774
2775//
2776// GenerateDragGesture
2777//
2778// If we're in the TRACKING state of the d&d gesture tracker, check the current
2779// position of the mouse in relation to the old one. If we've moved a sufficient
2780// amount from the mouse down, then fire off a drag gesture event.
2781void EventStateManager::GenerateDragGesture(
2782 nsPresContext* aPresContext,
2783 WidgetInputEvent& aMouseOrTouchOrPointerEvent) {
2784 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"
, 2784); MOZ_PretendNoReturn(); } } while (0)
;
2785 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"
, 2786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.AsMouseEvent()->IsReal()"
")"); do { MOZ_CrashSequence(__null, 2786); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2786 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"
, 2786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.AsMouseEvent()->IsReal()"
")"); do { MOZ_CrashSequence(__null, 2786); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2787 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", 2790
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
")"); do { MOZ_CrashSequence(__null, 2790); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2788 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", 2790
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
")"); do { MOZ_CrashSequence(__null, 2790); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2789 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", 2790
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
")"); do { MOZ_CrashSequence(__null, 2790); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2790 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", 2790
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
")"); do { MOZ_CrashSequence(__null, 2790); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2791 if (!IsTrackingDragGesture()) {
2792 return;
2793 }
2794
2795 AutoWeakFrame targetFrameBefore = mCurrentTarget;
2796 auto autoRestore = MakeScopeExit([&] { mCurrentTarget = targetFrameBefore; });
2797
2798 mCurrentTarget = nullptr;
2799 // Try to find a suitable frame by looping through the ancestors chain.
2800 for (auto* content :
2801 mGestureDownFrameOwner->InclusiveFlatTreeAncestorsOfType<nsIContent>()) {
2802 if (nsIFrame* target = content->GetPrimaryFrame()) {
2803 mCurrentTarget = target;
2804
2805 if (content != mGestureDownFrameOwner) {
2806 UpdateGestureContent(content);
2807 }
2808 break;
2809 }
2810 }
2811
2812 if (!mCurrentTarget || !mCurrentTarget->GetNearestWidget()) {
2813 StopTrackingDragGesture(true);
2814 return;
2815 }
2816
2817 // Check if selection is tracking drag gestures, if so
2818 // don't interfere!
2819 if (mCurrentTarget) {
2820 RefPtr<nsFrameSelection> frameSel = mCurrentTarget->GetFrameSelection();
2821 if (frameSel && frameSel->GetDragState()) {
2822 StopTrackingDragGesture(true);
2823 return;
2824 }
2825 }
2826
2827 // If non-native code is capturing the mouse don't start a drag.
2828 if (PresShell::IsMouseCapturePreventingDrag()) {
2829 StopTrackingDragGesture(true);
2830 return;
2831 }
2832
2833 if (!IsEventOutsideDragThreshold(aMouseOrTouchOrPointerEvent)) {
2834 // To keep the old behavior, flush layout even if we don't start dnd.
2835 FlushLayout(aPresContext);
2836 return;
2837 }
2838
2839 if (StaticPrefs::ui_click_hold_context_menus()) {
2840 // stop the click-hold before we fire off the drag gesture, in case
2841 // it takes a long time
2842 KillClickHoldTimer();
2843 }
2844
2845 nsCOMPtr<nsIDocShell> docshell = aPresContext->GetDocShell();
2846 if (!docshell) {
2847 return;
2848 }
2849
2850 nsCOMPtr<nsPIDOMWindowOuter> window = docshell->GetWindow();
2851 if (!window) return;
2852
2853 RefPtr<DataTransfer> dataTransfer =
2854 new DataTransfer(window, eDragStart, /* aIsExternal */ false,
2855 /* aClipboardType */ Nothing());
2856 auto protectDataTransfer = MakeScopeExit([&] {
2857 if (dataTransfer) {
2858 dataTransfer->Disconnect();
2859 }
2860 });
2861
2862 RefPtr<Selection> selection;
2863 RefPtr<RemoteDragStartData> remoteDragStartData;
2864 nsCOMPtr<nsIPrincipal> principal;
2865 nsCOMPtr<nsIPolicyContainer> policyContainer;
2866 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
2867 nsCOMPtr<nsIContent> targetContent;
2868 bool allowEmptyDataTransfer = false;
2869 if (const nsCOMPtr<nsIContent> eventContent =
2870 mCurrentTarget->GetExplicitEventTargetContent(
2871 aMouseOrTouchOrPointerEvent)) {
2872 // If the content is a text node in a password field, we shouldn't
2873 // allow to drag its raw text. Note that we've supported drag from
2874 // password fields but dragging data was masked text. So, it doesn't
2875 // make sense anyway.
2876 if (eventContent->IsText() && eventContent->HasFlag(NS_MAYBE_MASKED)) {
2877 // However, it makes sense to allow to drag selected password text
2878 // when copying selected password is allowed because users may want
2879 // to use drag and drop rather than copy and paste when web apps
2880 // request to input password twice for conforming new password but
2881 // they used password generator.
2882 const TextEditor* const textEditor =
2883 nsContentUtils::GetExtantTextEditorFromAnonymousNode(eventContent);
2884 if (!textEditor || !textEditor->IsCopyToClipboardAllowed()) {
2885 StopTrackingDragGesture(true);
2886 return;
2887 }
2888 }
2889 DetermineDragTargetAndDefaultData(
2890 window, eventContent, dataTransfer, &allowEmptyDataTransfer,
2891 getter_AddRefs(selection), getter_AddRefs(remoteDragStartData),
2892 getter_AddRefs(targetContent), getter_AddRefs(principal),
2893 getter_AddRefs(policyContainer), getter_AddRefs(cookieJarSettings));
2894 }
2895
2896 // Stop tracking the drag gesture now. This should stop us from
2897 // reentering GenerateDragGesture inside DOM event processing.
2898 // Pass false to avoid clearing the child process state since a real
2899 // drag should be starting.
2900 StopTrackingDragGesture(false);
2901
2902 if (MOZ_UNLIKELY(!targetContent)(__builtin_expect(!!(!targetContent), 0))) {
2903 return;
2904 }
2905
2906 // Use our targetContent, now that we've determined it, as the
2907 // parent object of the DataTransfer.
2908 nsCOMPtr<nsIContent> parentContent =
2909 targetContent->FindFirstNonChromeOnlyAccessContent();
2910 dataTransfer->SetParentObject(parentContent);
2911
2912 sLastDragOverFrame = nullptr;
2913 nsCOMPtr<nsIWidget> widget = mCurrentTarget->GetNearestWidget();
2914
2915 // get the widget from the target frame
2916 WidgetDragEvent startEvent(aMouseOrTouchOrPointerEvent.IsTrusted(),
2917 eDragStart, widget);
2918 startEvent.mFlags.mIsSynthesizedForTests =
2919 aMouseOrTouchOrPointerEvent.mFlags.mIsSynthesizedForTests;
2920 startEvent.mFlags.mIsAsyncSynthesizedForTests =
2921 aMouseOrTouchOrPointerEvent.mFlags.mIsAsyncSynthesizedForTests;
2922 FillInEventFromGestureDown(&startEvent);
2923
2924 startEvent.mDataTransfer = dataTransfer;
2925 switch (aMouseOrTouchOrPointerEvent.mClass) {
2926 case eMouseEventClass:
2927 case ePointerEventClass:
2928 startEvent.mInputSource =
2929 static_cast<const WidgetMouseEvent&>(aMouseOrTouchOrPointerEvent)
2930 .mInputSource;
2931 break;
2932 case eTouchEventClass:
2933 startEvent.mInputSource = MouseEvent_Binding::MOZ_SOURCE_TOUCH;
2934 break;
2935 default:
2936 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"
, 2936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")")
; do { MOZ_CrashSequence(__null, 2936); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2937 }
2938
2939 // Dispatch to the DOM. By setting mCurrentTarget we are faking
2940 // out the ESM and telling it that the current target frame is
2941 // actually where the mouseDown occurred, otherwise it will use
2942 // the frame the mouse is currently over which may or may not be
2943 // the same.
2944
2945 // Hold onto old target content through the event and reset after.
2946 nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
2947
2948 {
2949 AutoConnectedAncestorTracker trackTargetContent(*targetContent);
2950 // Set the current target to the content for the mouse down
2951 mCurrentTargetContent = targetContent;
2952
2953 // Dispatch the dragstart event to the DOM.
2954 nsEventStatus status = nsEventStatus_eIgnore;
2955 EventDispatcher::Dispatch(targetContent, aPresContext, &startEvent, nullptr,
2956 &status);
2957
2958 WidgetDragEvent* event = &startEvent;
2959
2960 // Emit observer event to allow addons to modify the DataTransfer
2961 // object.
2962 if (nsCOMPtr<nsIObserverService> observerService =
2963 mozilla::services::GetObserverService()) {
2964 observerService->NotifyObservers(dataTransfer,
2965 "on-datatransfer-available", nullptr);
2966 }
2967
2968 if (status != nsEventStatus_eConsumeNoDefault) {
2969 bool dragStarted = DoDefaultDragStart(
2970 aPresContext, event, dataTransfer, allowEmptyDataTransfer,
2971 targetContent, selection, remoteDragStartData, principal,
2972 policyContainer, cookieJarSettings);
2973 if (dragStarted) {
2974 sActiveESM = nullptr;
2975 aMouseOrTouchOrPointerEvent.StopPropagation();
2976 // XXX If all elements were removed from the document, we may need to
2977 // dispatch ePointerCancel on the Document node.
2978 if ((targetContent = trackTargetContent.GetConnectedContent())) {
2979 MaybeDispatchPointerCancel(aMouseOrTouchOrPointerEvent,
2980 *targetContent);
2981 }
2982 }
2983 }
2984 }
2985
2986 // Reset mCurretTargetContent to what it was
2987 mCurrentTargetContent = std::move(targetBeforeEvent);
2988
2989 // Now flush all pending notifications, for better responsiveness
2990 // while dragging.
2991 FlushLayout(aPresContext);
2992} // GenerateDragGesture
2993
2994void EventStateManager::DetermineDragTargetAndDefaultData(
2995 nsPIDOMWindowOuter* aWindow, nsIContent* aSelectionTarget,
2996 DataTransfer* aDataTransfer, bool* aAllowEmptyDataTransfer,
2997 Selection** aSelection, RemoteDragStartData** aRemoteDragStartData,
2998 nsIContent** aTargetNode, nsIPrincipal** aPrincipal,
2999 nsIPolicyContainer** aPolicyContainer,
3000 nsICookieJarSettings** aCookieJarSettings) {
3001 *aTargetNode = nullptr;
3002 *aAllowEmptyDataTransfer = false;
3003 nsCOMPtr<nsIContent> dragDataNode;
3004
3005 nsIContent* editingElement = aSelectionTarget->IsEditable()
3006 ? aSelectionTarget->GetEditingHost()
3007 : nullptr;
3008 nsCOMPtr<nsIPrincipal> principal;
3009 bool fromChildProcess = false;
3010
3011 // In chrome, only allow dragging inside editable areas.
3012 bool isChromeContext = !aWindow->GetBrowsingContext()->IsContent();
3013 if (isChromeContext && !editingElement) {
3014 if (mGestureDownDragStartData) {
3015 // A child process started a drag so use any data it assigned for the dnd
3016 // session.
3017 mGestureDownDragStartData->AddInitialDnDDataTo(
3018 aDataTransfer, getter_AddRefs(principal), aPolicyContainer,
3019 aCookieJarSettings);
3020 fromChildProcess = true;
3021 mGestureDownDragStartData.forget(aRemoteDragStartData);
3022 *aAllowEmptyDataTransfer = true;
3023 }
3024 } else {
3025 mGestureDownDragStartData = nullptr;
3026
3027 // GetDragData determines if a selection, link or image in the content
3028 // should be dragged, and places the data associated with the drag in the
3029 // data transfer.
3030 // mGestureDownContent is the node where the mousedown event for the drag
3031 // occurred, and aSelectionTarget is the node to use when a selection is
3032 // used
3033 bool canDrag;
3034 bool wasAlt = (mGestureModifiers & MODIFIER_ALT) != 0;
3035 nsresult rv = nsContentAreaDragDrop::GetDragData(
3036 aWindow, mGestureDownContent, aSelectionTarget, wasAlt, aDataTransfer,
3037 &canDrag, aSelection, getter_AddRefs(dragDataNode), aPolicyContainer,
3038 aCookieJarSettings);
3039 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !canDrag) {
3040 return;
3041 }
3042 }
3043
3044 // if GetDragData returned a node, use that as the node being dragged.
3045 // Otherwise, if a selection is being dragged, use the node within the
3046 // selection that was dragged. Otherwise, just use the mousedown target.
3047 nsIContent* dragContent = mGestureDownContent;
3048 if (dragDataNode)
3049 dragContent = dragDataNode;
3050 else if (*aSelection)
3051 dragContent = aSelectionTarget;
3052
3053 nsIContent* originalDragContent = dragContent;
3054
3055 // If a selection isn't being dragged, look for an ancestor with the
3056 // draggable property set. If one is found, use that as the target of the
3057 // drag instead of the node that was clicked on. If a draggable node wasn't
3058 // found, just use the clicked node.
3059 if (!*aSelection) {
3060 while (dragContent) {
3061 if (auto htmlElement = nsGenericHTMLElement::FromNode(dragContent)) {
3062 if (htmlElement->Draggable()) {
3063 // We let draggable elements to trigger dnd even if there is no data
3064 // in the DataTransfer.
3065 *aAllowEmptyDataTransfer = true;
3066 break;
3067 }
3068 } else {
3069 if (dragContent->IsXULElement()) {
3070 // All XUL elements are draggable, so if a XUL element is
3071 // encountered, stop looking for draggable nodes and just use the
3072 // original clicked node instead.
3073 // XXXndeakin
3074 // In the future, we will want to improve this so that XUL has a
3075 // better way to specify whether something is draggable than just
3076 // on/off.
3077 dragContent = mGestureDownContent;
3078 break;
3079 }
3080 // otherwise, it's not an HTML or XUL element, so just keep looking
3081 }
3082 dragContent = dragContent->GetFlattenedTreeParent();
3083 }
3084 }
3085
3086 // if no node in the hierarchy was found to drag, but the GetDragData method
3087 // returned a node, use that returned node. Otherwise, nothing is draggable.
3088 if (!dragContent && dragDataNode) dragContent = dragDataNode;
3089
3090 if (dragContent) {
3091 // if an ancestor node was used instead, clear the drag data
3092 // XXXndeakin rework this a bit. Find a way to just not call GetDragData if
3093 // we don't need to.
3094 if (dragContent != originalDragContent) aDataTransfer->ClearAll();
3095 *aTargetNode = dragContent;
3096 NS_ADDREF(*aTargetNode)(*aTargetNode)->AddRef();
3097 if (!fromChildProcess) {
3098 principal = dragContent->NodePrincipal();
3099 }
3100 principal.forget(aPrincipal);
3101 }
3102}
3103
3104bool EventStateManager::DoDefaultDragStart(
3105 nsPresContext* aPresContext, WidgetDragEvent* aDragEvent,
3106 DataTransfer* aDataTransfer, bool aAllowEmptyDataTransfer,
3107 nsIContent* aDragTarget, Selection* aSelection,
3108 RemoteDragStartData* aDragStartData, nsIPrincipal* aPrincipal,
3109 nsIPolicyContainer* aPolicyContainer,
3110 nsICookieJarSettings* aCookieJarSettings) {
3111 nsCOMPtr<nsIDragService> dragService =
3112 do_GetService("@mozilla.org/widget/dragservice;1");
3113 if (!dragService) return false;
3114
3115 // Default handling for the dragstart event.
3116 //
3117 // First, check if a drag session already exists. This means that the drag
3118 // service was called directly within a draggesture handler. In this case,
3119 // don't do anything more, as it is assumed that the handler is managing
3120 // drag and drop manually. Make sure to return true to indicate that a drag
3121 // began. However, if we're handling drag session for synthesized events,
3122 // we need to initialize some information of the session. Therefore, we
3123 // need to keep going for synthesized case.
3124 if (MOZ_UNLIKELY(!mPresContext)(__builtin_expect(!!(!mPresContext), 0))) {
3125 return true;
3126 }
3127 nsCOMPtr<nsIDragSession> dragSession =
3128 dragService->GetCurrentSession(mPresContext->GetRootWidget());
3129 if (dragSession && !dragSession->IsSynthesizedForTests()) {
3130 return true;
3131 }
3132
3133 // No drag session is currently active, so check if a handler added
3134 // any items to be dragged. If not, there isn't anything to drag.
3135 uint32_t count = 0;
3136 if (aDataTransfer) {
3137 count = aDataTransfer->MozItemCount();
3138 }
3139 if (!aAllowEmptyDataTransfer && !count) {
3140 return false;
3141 }
3142
3143 // Get the target being dragged, which may not be the same as the
3144 // target of the mouse event. If one wasn't set in the
3145 // aDataTransfer during the event handler, just use the original
3146 // target instead.
3147 nsCOMPtr<nsIContent> dragTarget = aDataTransfer->GetDragTarget();
3148 if (!dragTarget) {
3149 dragTarget = aDragTarget;
3150 if (!dragTarget) {
3151 return false;
3152 }
3153 }
3154
3155 // check which drag effect should initially be used. If the effect was not
3156 // set, just use all actions, otherwise Windows won't allow a drop.
3157 uint32_t action = aDataTransfer->EffectAllowedInt();
3158 if (action == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) {
3159 action = nsIDragService::DRAGDROP_ACTION_COPY |
3160 nsIDragService::DRAGDROP_ACTION_MOVE |
3161 nsIDragService::DRAGDROP_ACTION_LINK;
3162 }
3163
3164 // get any custom drag image that was set
3165 int32_t imageX, imageY;
3166 RefPtr<Element> dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
3167
3168 nsCOMPtr<nsIArray> transArray = aDataTransfer->GetTransferables(dragTarget);
3169 if (!transArray) {
3170 return false;
3171 }
3172
3173 RefPtr<DataTransfer> dataTransfer;
3174 if (!dragSession) {
3175 // After this function returns, the DataTransfer will be cleared so it
3176 // appears empty to content. We need to pass a DataTransfer into the Drag
3177 // Session, so we need to make a copy.
3178 aDataTransfer->Clone(aDragTarget, eDrop, aDataTransfer->MozUserCancelled(),
3179 false, getter_AddRefs(dataTransfer));
3180
3181 // Copy over the drop effect, as Clone doesn't copy it for us.
3182 dataTransfer->SetDropEffectInt(aDataTransfer->DropEffectInt());
3183 } else {
3184 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", 3184
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dragSession->IsSynthesizedForTests()"
")"); do { MOZ_CrashSequence(__null, 3184); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3185 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", 3185
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDragEvent->mFlags.mIsSynthesizedForTests"
")"); do { MOZ_CrashSequence(__null, 3185); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3186 // If we're initializing synthesized drag session, we should use given
3187 // DataTransfer as is because it'll be used with following drag events
3188 // in any tests, therefore it should be set to nsIDragSession.dataTransfer
3189 // because it and DragEvent.dataTransfer should be same instance.
3190 dataTransfer = aDataTransfer;
3191 }
3192
3193 // XXXndeakin don't really want to create a new drag DOM event
3194 // here, but we need something to pass to the InvokeDragSession
3195 // methods.
3196 RefPtr<DragEvent> event =
3197 NS_NewDOMDragEvent(dragTarget, aPresContext, aDragEvent);
3198
3199 // Use InvokeDragSessionWithSelection if a selection is being dragged,
3200 // such that the image can be generated from the selected text. However,
3201 // use InvokeDragSessionWithImage if a custom image was set or something
3202 // other than a selection is being dragged.
3203 if (!dragImage && aSelection) {
3204 dragService->InvokeDragSessionWithSelection(
3205 aSelection, aPrincipal, aPolicyContainer, aCookieJarSettings,
3206 transArray, action, event, dataTransfer, dragTarget);
3207 } else if (aDragStartData) {
3208 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", 3208
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3208); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3209 dragService->InvokeDragSessionWithRemoteImage(
3210 dragTarget, aPrincipal, aPolicyContainer, aCookieJarSettings,
3211 transArray, action, aDragStartData, event, dataTransfer);
3212 } else {
3213 dragService->InvokeDragSessionWithImage(
3214 dragTarget, aPrincipal, aPolicyContainer, aCookieJarSettings,
3215 transArray, action, dragImage, imageX, imageY, event, dataTransfer);
3216 }
3217
3218 return true;
3219}
3220
3221void EventStateManager::ChangeZoom(bool aIncrease) {
3222 // Send the zoom change to the top level browser so it will be handled by the
3223 // front end in the same way as other zoom actions.
3224 nsIDocShell* docShell = mDocument->GetDocShell();
3225 if (!docShell) {
3226 return;
3227 }
3228
3229 BrowsingContext* bc = docShell->GetBrowsingContext();
3230 if (!bc) {
3231 return;
3232 }
3233
3234 if (XRE_IsParentProcess()) {
3235 bc->Canonical()->DispatchWheelZoomChange(aIncrease);
3236 } else if (BrowserChild* child = BrowserChild::GetFrom(docShell)) {
3237 child->SendWheelZoomChange(aIncrease);
3238 }
3239}
3240
3241void EventStateManager::DoScrollHistory(int32_t direction) {
3242 nsCOMPtr<nsISupports> pcContainer(mPresContext->GetContainerWeak());
3243 if (pcContainer) {
3244 nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(pcContainer));
3245 if (webNav) {
3246 // positive direction to go back one step, nonpositive to go forward
3247 // This is doing user-initiated history traversal, hence we want
3248 // to require that history entries we navigate to have user interaction.
3249 if (direction > 0)
3250 webNav->GoBack(StaticPrefs::browser_navigation_requireUserInteraction(),
3251 true);
3252 else
3253 webNav->GoForward(
3254 StaticPrefs::browser_navigation_requireUserInteraction(), true);
3255 }
3256 }
3257}
3258
3259void EventStateManager::DoScrollZoom(nsIFrame* aTargetFrame,
3260 int32_t adjustment) {
3261 // Exclude content in chrome docshells.
3262 nsIContent* content = aTargetFrame->GetContent();
3263 if (content && !nsContentUtils::IsInChromeDocshell(content->OwnerDoc())) {
3264 // Positive adjustment to decrease zoom, negative to increase
3265 const bool increase = adjustment <= 0;
3266 EnsureDocument(mPresContext);
3267 ChangeZoom(increase);
3268 }
3269}
3270
3271static nsIFrame* GetParentFrameToScroll(nsIFrame* aFrame) {
3272 if (!aFrame) return nullptr;
3273
3274 if (aFrame->StyleDisplay()->mPosition == StylePositionProperty::Fixed &&
3275 nsLayoutUtils::IsReallyFixedPos(aFrame)) {
3276 return aFrame->PresShell()->GetRootScrollContainerFrame();
3277 }
3278 return aFrame->GetParent();
3279}
3280
3281void EventStateManager::DispatchLegacyMouseScrollEvents(
3282 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent, nsEventStatus* aStatus) {
3283 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"
, 3283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 3283); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3284 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"
, 3284); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 3284); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3285
3286 if (!aTargetFrame || *aStatus == nsEventStatus_eConsumeNoDefault) {
3287 return;
3288 }
3289
3290 // Ignore mouse wheel transaction for computing legacy mouse wheel
3291 // events' delta value.
3292 // DOM event's delta vales are computed from CSS pixels.
3293 auto scrollAmountInCSSPixels =
3294 CSSIntSize::FromAppUnitsRounded(aEvent->mScrollAmount);
3295
3296 // XXX We don't deal with fractional amount in legacy event, though the
3297 // default action handler (DoScrollText()) deals with it.
3298 // If we implemented such strict computation, we would need additional
3299 // accumulated delta values. It would made the code more complicated.
3300 // And also it would computes different delta values from older version.
3301 // It doesn't make sense to implement such code for legacy events and
3302 // rare cases.
3303 int32_t scrollDeltaX, scrollDeltaY, pixelDeltaX, pixelDeltaY;
3304 switch (aEvent->mDeltaMode) {
3305 case WheelEvent_Binding::DOM_DELTA_PAGE:
3306 scrollDeltaX = !aEvent->mLineOrPageDeltaX
3307 ? 0
3308 : (aEvent->mLineOrPageDeltaX > 0
3309 ? UIEvent_Binding::SCROLL_PAGE_DOWN
3310 : UIEvent_Binding::SCROLL_PAGE_UP);
3311 scrollDeltaY = !aEvent->mLineOrPageDeltaY
3312 ? 0
3313 : (aEvent->mLineOrPageDeltaY > 0
3314 ? UIEvent_Binding::SCROLL_PAGE_DOWN
3315 : UIEvent_Binding::SCROLL_PAGE_UP);
3316 pixelDeltaX = RoundDown(aEvent->mDeltaX * scrollAmountInCSSPixels.width);
3317 pixelDeltaY = RoundDown(aEvent->mDeltaY * scrollAmountInCSSPixels.height);
3318 break;
3319
3320 case WheelEvent_Binding::DOM_DELTA_LINE:
3321 scrollDeltaX = aEvent->mLineOrPageDeltaX;
3322 scrollDeltaY = aEvent->mLineOrPageDeltaY;
3323 pixelDeltaX = RoundDown(aEvent->mDeltaX * scrollAmountInCSSPixels.width);
3324 pixelDeltaY = RoundDown(aEvent->mDeltaY * scrollAmountInCSSPixels.height);
3325 break;
3326
3327 case WheelEvent_Binding::DOM_DELTA_PIXEL:
3328 scrollDeltaX = aEvent->mLineOrPageDeltaX;
3329 scrollDeltaY = aEvent->mLineOrPageDeltaY;
3330 pixelDeltaX = RoundDown(aEvent->mDeltaX);
3331 pixelDeltaY = RoundDown(aEvent->mDeltaY);
3332 break;
3333
3334 default:
3335 MOZ_CRASH("Invalid deltaMode value comes")do { do { } while (false); MOZ_ReportCrash("" "Invalid deltaMode value comes"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3335
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid deltaMode value comes"
")"); do { MOZ_CrashSequence(__null, 3335); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
3336 }
3337
3338 // Send the legacy events in following order:
3339 // 1. Vertical scroll
3340 // 2. Vertical pixel scroll (even if #1 isn't consumed)
3341 // 3. Horizontal scroll (even if #1 and/or #2 are consumed)
3342 // 4. Horizontal pixel scroll (even if #3 isn't consumed)
3343
3344 AutoWeakFrame targetFrame(aTargetFrame);
3345
3346 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"
, 3349); 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, 3349); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3347 !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"
, 3349); 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, 3349); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3348 "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"
, 3349); 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, 3349); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3349 "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"
, 3349); 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, 3349); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3350 EventState stateX, stateY;
3351 if (scrollDeltaY) {
3352 SendLineScrollEvent(aTargetFrame, aEvent, stateY, scrollDeltaY,
3353 DELTA_DIRECTION_Y);
3354 if (!targetFrame.IsAlive()) {
3355 *aStatus = nsEventStatus_eConsumeNoDefault;
3356 return;
3357 }
3358 }
3359
3360 if (pixelDeltaY) {
3361 SendPixelScrollEvent(aTargetFrame, aEvent, stateY, pixelDeltaY,
3362 DELTA_DIRECTION_Y);
3363 if (!targetFrame.IsAlive()) {
3364 *aStatus = nsEventStatus_eConsumeNoDefault;
3365 return;
3366 }
3367 }
3368
3369 if (scrollDeltaX) {
3370 SendLineScrollEvent(aTargetFrame, aEvent, stateX, scrollDeltaX,
3371 DELTA_DIRECTION_X);
3372 if (!targetFrame.IsAlive()) {
3373 *aStatus = nsEventStatus_eConsumeNoDefault;
3374 return;
3375 }
3376 }
3377
3378 if (pixelDeltaX) {
3379 SendPixelScrollEvent(aTargetFrame, aEvent, stateX, pixelDeltaX,
3380 DELTA_DIRECTION_X);
3381 if (!targetFrame.IsAlive()) {
3382 *aStatus = nsEventStatus_eConsumeNoDefault;
3383 return;
3384 }
3385 }
3386
3387 if (stateY.mDefaultPrevented) {
3388 *aStatus = nsEventStatus_eConsumeNoDefault;
3389 aEvent->PreventDefault(!stateY.mDefaultPreventedByContent);
3390 }
3391
3392 if (stateX.mDefaultPrevented) {
3393 *aStatus = nsEventStatus_eConsumeNoDefault;
3394 aEvent->PreventDefault(!stateX.mDefaultPreventedByContent);
3395 }
3396}
3397
3398void EventStateManager::SendLineScrollEvent(nsIFrame* aTargetFrame,
3399 WidgetWheelEvent* aEvent,
3400 EventState& aState, int32_t aDelta,
3401 DeltaDirection aDeltaDirection) {
3402 nsCOMPtr<nsIContent> targetContent = aTargetFrame->GetContent();
3403 if (!targetContent) {
3404 targetContent = GetFocusedElement();
3405 if (!targetContent) {
3406 return;
3407 }
3408 }
3409
3410 while (targetContent->IsText()) {
3411 targetContent = targetContent->GetFlattenedTreeParent();
3412 }
3413
3414 WidgetMouseScrollEvent event(aEvent->IsTrusted(),
3415 eLegacyMouseLineOrPageScroll, aEvent->mWidget);
3416 event.mFlags.mDefaultPrevented = aState.mDefaultPrevented;
3417 event.mFlags.mDefaultPreventedByContent = aState.mDefaultPreventedByContent;
3418 event.mRefPoint = aEvent->mRefPoint;
3419 event.mTimeStamp = aEvent->mTimeStamp;
3420 event.mModifiers = aEvent->mModifiers;
3421 event.mButtons = aEvent->mButtons;
3422 event.mIsHorizontal = (aDeltaDirection == DELTA_DIRECTION_X);
3423 event.mDelta = aDelta;
3424 event.mInputSource = aEvent->mInputSource;
3425
3426 RefPtr<nsPresContext> presContext = aTargetFrame->PresContext();
3427 nsEventStatus status = nsEventStatus_eIgnore;
3428 EventDispatcher::Dispatch(targetContent, presContext, &event, nullptr,
3429 &status);
3430 aState.mDefaultPrevented =
3431 event.DefaultPrevented() || status == nsEventStatus_eConsumeNoDefault;
3432 aState.mDefaultPreventedByContent = event.DefaultPreventedByContent();
3433}
3434
3435void EventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
3436 WidgetWheelEvent* aEvent,
3437 EventState& aState,
3438 int32_t aPixelDelta,
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(), eLegacyMousePixelScroll,
3453 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 = aPixelDelta;
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
3473ScrollContainerFrame*
3474EventStateManager::ComputeScrollTargetAndMayAdjustWheelEvent(
3475 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent,
3476 ComputeScrollTargetOptions aOptions) {
3477 return ComputeScrollTargetAndMayAdjustWheelEvent(
3478 aTargetFrame, aEvent->mDeltaX, aEvent->mDeltaY, aEvent, aOptions);
3479}
3480
3481// Overload ComputeScrollTargetAndMayAdjustWheelEvent method to allow passing
3482// "test" dx and dy when looking for which scrollbarmediators to activate when
3483// two finger down on trackpad and before any actual motion
3484ScrollContainerFrame*
3485EventStateManager::ComputeScrollTargetAndMayAdjustWheelEvent(
3486 nsIFrame* aTargetFrame, double aDirectionX, double aDirectionY,
3487 WidgetWheelEvent* aEvent, ComputeScrollTargetOptions aOptions) {
3488 bool isAutoDir = false;
3489 bool honoursRoot = false;
3490 if (MAY_BE_ADJUSTED_BY_AUTO_DIR & aOptions) {
3491 // If the scroll is respected as auto-dir, aDirection* should always be
3492 // equivalent to the event's delta vlaues(Currently, there are only one case
3493 // where aDirection*s have different values from the widget wheel event's
3494 // original delta values and the only case isn't auto-dir, see
3495 // ScrollbarsForWheel::TemporarilyActivateAllPossibleScrollTargets).
3496 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", 3497
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDirectionX == aEvent->mDeltaX && aDirectionY == aEvent->mDeltaY"
")"); do { MOZ_CrashSequence(__null, 3497); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3497 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", 3497
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDirectionX == aEvent->mDeltaX && aDirectionY == aEvent->mDeltaY"
")"); do { MOZ_CrashSequence(__null, 3497); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3498
3499 WheelDeltaAdjustmentStrategy strategy =
3500 GetWheelDeltaAdjustmentStrategy(*aEvent);
3501 switch (strategy) {
3502 case WheelDeltaAdjustmentStrategy::eAutoDir:
3503 isAutoDir = true;
3504 honoursRoot = false;
3505 break;
3506 case WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour:
3507 isAutoDir = true;
3508 honoursRoot = true;
3509 break;
3510 default:
3511 break;
3512 }
3513 }
3514
3515 if (aOptions & PREFER_MOUSE_WHEEL_TRANSACTION) {
3516 // If the user recently scrolled with the mousewheel, then they probably
3517 // want to scroll the same view as before instead of the view under the
3518 // cursor. WheelTransaction tracks the frame currently being
3519 // scrolled with the mousewheel. We consider the transaction ended when the
3520 // mouse moves more than "mousewheel.transaction.ignoremovedelay"
3521 // milliseconds after the last scroll operation, or any time the mouse moves
3522 // out of the frame, or when more than "mousewheel.transaction.timeout"
3523 // milliseconds have passed after the last operation, even if the mouse
3524 // hasn't moved.
3525 nsIFrame* lastScrollFrame = WheelTransaction::GetScrollTargetFrame();
3526 if (lastScrollFrame) {
3527 ScrollContainerFrame* scrollContainerFrame =
3528 lastScrollFrame->GetScrollTargetFrame();
3529 if (scrollContainerFrame) {
3530 if (isAutoDir) {
3531 ESMAutoDirWheelDeltaAdjuster adjuster(*aEvent, *lastScrollFrame,
3532 honoursRoot);
3533 // Note that calling this function will not always cause the delta to
3534 // be adjusted, it only adjusts the delta when it should, because
3535 // Adjust() internally calls ShouldBeAdjusted() before making
3536 // adjustment.
3537 adjuster.Adjust();
3538 }
3539 return scrollContainerFrame;
3540 }
3541 }
3542 }
3543
3544 // If the event doesn't cause scroll actually, we cannot find scroll target
3545 // because we check if the event can cause scroll actually on each found
3546 // scrollable frame.
3547 if (!aDirectionX && !aDirectionY) {
3548 return nullptr;
3549 }
3550
3551 bool checkIfScrollableX;
3552 bool checkIfScrollableY;
3553 if (isAutoDir) {
3554 // Always check the frame's scrollability in both the two directions for an
3555 // auto-dir scroll. That is, for an auto-dir scroll,
3556 // PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS and
3557 // PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS should be ignored.
3558 checkIfScrollableX = true;
3559 checkIfScrollableY = true;
3560 } else {
3561 checkIfScrollableX =
3562 aDirectionX &&
3563 (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS);
3564 checkIfScrollableY =
3565 aDirectionY &&
3566 (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS);
3567 }
3568
3569 nsIFrame* scrollFrame = !(aOptions & START_FROM_PARENT)
3570 ? aTargetFrame
3571 : GetParentFrameToScroll(aTargetFrame);
3572 for (; scrollFrame; scrollFrame = GetParentFrameToScroll(scrollFrame)) {
3573 // Check whether the frame wants to provide us with a scrollable view.
3574 ScrollContainerFrame* scrollContainerFrame =
3575 scrollFrame->GetScrollTargetFrame();
3576 if (!scrollContainerFrame) {
3577 nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(scrollFrame);
3578 if (menuPopupFrame) {
3579 return nullptr;
3580 }
3581 continue;
3582 }
3583
3584 if (!checkIfScrollableX && !checkIfScrollableY) {
3585 return scrollContainerFrame;
3586 }
3587
3588 // If the frame disregards the direction the user is trying to scroll, then
3589 // it should just bubbles the scroll event up to its parental scroll frame
3590
3591 Maybe<layers::ScrollDirection> disregardedDirection =
3592 WheelHandlingUtils::GetDisregardedWheelScrollDirection(scrollFrame);
3593 if (disregardedDirection) {
3594 switch (disregardedDirection.ref()) {
3595 case layers::ScrollDirection::eHorizontal:
3596 if (checkIfScrollableX) {
3597 continue;
3598 }
3599 break;
3600 case layers::ScrollDirection::eVertical:
3601 if (checkIfScrollableY) {
3602 continue;
3603 }
3604 break;
3605 }
3606 }
3607
3608 layers::ScrollDirections directions =
3609 scrollContainerFrame
3610 ->GetAvailableScrollingDirectionsForUserInputEvents();
3611 if ((!(directions.contains(layers::ScrollDirection::eVertical)) &&
3612 !(directions.contains(layers::ScrollDirection::eHorizontal))) ||
3613 (checkIfScrollableY && !checkIfScrollableX &&
3614 !(directions.contains(layers::ScrollDirection::eVertical))) ||
3615 (checkIfScrollableX && !checkIfScrollableY &&
3616 !(directions.contains(layers::ScrollDirection::eHorizontal)))) {
3617 continue;
3618 }
3619
3620 // Computes whether the currently checked frame is scrollable by this wheel
3621 // event.
3622 bool canScroll = false;
3623 if (isAutoDir) {
3624 ESMAutoDirWheelDeltaAdjuster adjuster(*aEvent, *scrollFrame, honoursRoot);
3625 if (adjuster.ShouldBeAdjusted()) {
3626 adjuster.Adjust();
3627 canScroll = true;
3628 } else if (WheelHandlingUtils::CanScrollOn(scrollContainerFrame,
3629 aDirectionX, aDirectionY)) {
3630 canScroll = true;
3631 }
3632 } else if (WheelHandlingUtils::CanScrollOn(scrollContainerFrame,
3633 aDirectionX, aDirectionY)) {
3634 canScroll = true;
3635 }
3636
3637 if (canScroll) {
3638 return scrollContainerFrame;
3639 }
3640
3641 // Where we are at is the block ending in a for loop.
3642 // The current frame has been checked to be unscrollable by this wheel
3643 // event, continue the loop to check its parent, if any.
3644 }
3645
3646 nsIFrame* newFrame = nsLayoutUtils::GetCrossDocParentFrameInProcess(
3647 aTargetFrame->PresShell()->GetRootFrame());
3648 aOptions =
3649 static_cast<ComputeScrollTargetOptions>(aOptions & ~START_FROM_PARENT);
3650 if (!newFrame) {
3651 return nullptr;
3652 }
3653 return ComputeScrollTargetAndMayAdjustWheelEvent(newFrame, aEvent, aOptions);
3654}
3655
3656nsSize EventStateManager::GetScrollAmount(
3657 nsPresContext* aPresContext, WidgetWheelEvent* aEvent,
3658 ScrollContainerFrame* aScrollContainerFrame) {
3659 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"
, 3659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
")"); do { MOZ_CrashSequence(__null, 3659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3660 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"
, 3660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 3660); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3661
3662 const bool isPage = aEvent->mDeltaMode == WheelEvent_Binding::DOM_DELTA_PAGE;
3663 if (!aScrollContainerFrame) {
3664 // If there is no scrollable frame, we should use root, see below.
3665 aScrollContainerFrame =
3666 aPresContext->PresShell()->GetRootScrollContainerFrame();
3667 }
3668
3669 if (aScrollContainerFrame) {
3670 return isPage ? aScrollContainerFrame->GetPageScrollAmount()
3671 : aScrollContainerFrame->GetLineScrollAmount();
3672 }
3673
3674 // If there is no scrollable frame and page scrolling, use viewport size.
3675 if (isPage) {
3676 return aPresContext->GetVisibleArea().Size();
3677 }
3678
3679 // Otherwise use root frame's font metrics.
3680 //
3681 // FIXME(emilio): Should this use the root element's style frame? The root
3682 // frame will always have the initial font. Then again it should never matter
3683 // for content, we should always have a root scrollable frame in html
3684 // documents.
3685 nsIFrame* rootFrame = aPresContext->PresShell()->GetRootFrame();
3686 if (!rootFrame) {
3687 return nsSize(0, 0);
3688 }
3689 RefPtr<nsFontMetrics> fm =
3690 nsLayoutUtils::GetInflatedFontMetricsForFrame(rootFrame);
3691 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"
, 3691); return nsSize(0, 0); } } while (false)
;
3692 return nsSize(fm->AveCharWidth(), fm->MaxHeight());
3693}
3694
3695void EventStateManager::DoScrollText(
3696 ScrollContainerFrame* aScrollContainerFrame, WidgetWheelEvent* aEvent) {
3697 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", 3697
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aScrollContainerFrame"
")"); 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 AutoWeakFrame scrollFrameWeak(aScrollContainerFrame);
3701 AutoWeakFrame eventFrameWeak(mCurrentTarget);
3702 if (!WheelTransaction::WillHandleDefaultAction(aEvent, scrollFrameWeak,
3703 eventFrameWeak)) {
3704 return;
3705 }
3706
3707 // Default action's actual scroll amount should be computed from device
3708 // pixels.
3709 nsPresContext* pc = aScrollContainerFrame->PresContext();
3710 nsSize scrollAmount = GetScrollAmount(pc, aEvent, aScrollContainerFrame);
3711 nsIntSize scrollAmountInDevPixels(
3712 pc->AppUnitsToDevPixels(scrollAmount.width),
3713 pc->AppUnitsToDevPixels(scrollAmount.height));
3714 nsIntPoint actualDevPixelScrollAmount =
3715 DeltaAccumulator::GetInstance()->ComputeScrollAmountForDefaultAction(
3716 aEvent, scrollAmountInDevPixels);
3717
3718 // Don't scroll around the axis whose overflow style is hidden.
3719 ScrollStyles overflowStyle = aScrollContainerFrame->GetScrollStyles();
3720 if (overflowStyle.mHorizontal == StyleOverflow::Hidden) {
3721 actualDevPixelScrollAmount.x = 0;
3722 }
3723 if (overflowStyle.mVertical == StyleOverflow::Hidden) {
3724 actualDevPixelScrollAmount.y = 0;
3725 }
3726
3727 ScrollSnapFlags snapFlags = ScrollSnapFlags::IntendedDirection;
3728 mozilla::ScrollOrigin origin = mozilla::ScrollOrigin::NotSpecified;
3729 switch (aEvent->mDeltaMode) {
3730 case WheelEvent_Binding::DOM_DELTA_LINE:
3731 origin = mozilla::ScrollOrigin::MouseWheel;
3732 break;
3733 case WheelEvent_Binding::DOM_DELTA_PAGE:
3734 origin = mozilla::ScrollOrigin::Pages;
3735 snapFlags |= ScrollSnapFlags::IntendedEndPosition;
3736 break;
3737 case WheelEvent_Binding::DOM_DELTA_PIXEL:
3738 origin = mozilla::ScrollOrigin::Pixels;
3739 break;
3740 default:
3741 MOZ_CRASH("Invalid deltaMode value comes")do { do { } while (false); MOZ_ReportCrash("" "Invalid deltaMode value comes"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3741
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid deltaMode value comes"
")"); do { MOZ_CrashSequence(__null, 3741); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
3742 }
3743
3744 // We shouldn't scroll more one page at once except when over one page scroll
3745 // is allowed for the event.
3746 nsSize pageSize = aScrollContainerFrame->GetPageScrollAmount();
3747 nsIntSize devPixelPageSize(pc->AppUnitsToDevPixels(pageSize.width),
3748 pc->AppUnitsToDevPixels(pageSize.height));
3749 if (!WheelPrefs::GetInstance()->IsOverOnePageScrollAllowedX(aEvent) &&
3750 Abs(actualDevPixelScrollAmount.x.value) >
3751 (unsigned)std::max(devPixelPageSize.width, 0)) {
3752 actualDevPixelScrollAmount.x = (actualDevPixelScrollAmount.x >= 0)
3753 ? devPixelPageSize.width
3754 : -devPixelPageSize.width;
3755 }
3756
3757 if (!WheelPrefs::GetInstance()->IsOverOnePageScrollAllowedY(aEvent) &&
3758 Abs(actualDevPixelScrollAmount.y.value) >
3759 (unsigned)std::max(devPixelPageSize.height, 0)) {
3760 actualDevPixelScrollAmount.y = (actualDevPixelScrollAmount.y >= 0)
3761 ? devPixelPageSize.height
3762 : -devPixelPageSize.height;
3763 }
3764
3765 bool isDeltaModePixel =
3766 (aEvent->mDeltaMode == WheelEvent_Binding::DOM_DELTA_PIXEL);
3767
3768 ScrollMode mode;
3769 switch (aEvent->mScrollType) {
3770 case WidgetWheelEvent::SCROLL_DEFAULT:
3771 if (isDeltaModePixel) {
3772 mode = ScrollMode::Normal;
3773 } else {
3774 mode = ScrollMode::Smooth;
3775 }
3776 break;
3777 case WidgetWheelEvent::SCROLL_SYNCHRONOUSLY:
3778 mode = ScrollMode::Instant;
3779 break;
3780 case WidgetWheelEvent::SCROLL_ASYNCHRONOUSLY:
3781 mode = ScrollMode::Normal;
3782 break;
3783 case WidgetWheelEvent::SCROLL_SMOOTHLY:
3784 mode = ScrollMode::Smooth;
3785 break;
3786 default:
3787 MOZ_CRASH("Invalid mScrollType value comes")do { do { } while (false); MOZ_ReportCrash("" "Invalid mScrollType value comes"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3787
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid mScrollType value comes"
")"); do { MOZ_CrashSequence(__null, 3787); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
3788 }
3789
3790 ScrollContainerFrame::ScrollMomentum momentum =
3791 aEvent->mIsMomentum ? ScrollContainerFrame::SYNTHESIZED_MOMENTUM_EVENT
3792 : ScrollContainerFrame::NOT_MOMENTUM;
3793
3794 nsIntPoint overflow;
3795 aScrollContainerFrame->ScrollBy(actualDevPixelScrollAmount,
3796 ScrollUnit::DEVICE_PIXELS, mode, &overflow,
3797 origin, momentum, snapFlags);
3798
3799 if (!scrollFrameWeak.IsAlive()) {
3800 // If the scroll causes changing the layout, we can think that the event
3801 // has been completely consumed by the content. Then, users probably don't
3802 // want additional action.
3803 aEvent->mOverflowDeltaX = aEvent->mOverflowDeltaY = 0;
3804 } else if (isDeltaModePixel) {
3805 aEvent->mOverflowDeltaX = overflow.x;
3806 aEvent->mOverflowDeltaY = overflow.y;
3807 } else {
3808 aEvent->mOverflowDeltaX =
3809 static_cast<double>(overflow.x) / scrollAmountInDevPixels.width;
3810 aEvent->mOverflowDeltaY =
3811 static_cast<double>(overflow.y) / scrollAmountInDevPixels.height;
3812 }
3813
3814 // If CSS overflow properties caused not to scroll, the overflowDelta* values
3815 // should be same as delta* values since they may be used as gesture event by
3816 // widget. However, if there is another scrollable element in the ancestor
3817 // along the axis, probably users don't want the operation to cause
3818 // additional action such as moving history. In such case, overflowDelta
3819 // values should stay zero.
3820 if (scrollFrameWeak.IsAlive()) {
3821 if (aEvent->mDeltaX && overflowStyle.mHorizontal == StyleOverflow::Hidden &&
3822 !ComputeScrollTargetAndMayAdjustWheelEvent(
3823 aScrollContainerFrame, aEvent,
3824 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS_WITH_AUTO_DIR)) {
3825 aEvent->mOverflowDeltaX = aEvent->mDeltaX;
3826 }
3827 if (aEvent->mDeltaY && overflowStyle.mVertical == StyleOverflow::Hidden &&
3828 !ComputeScrollTargetAndMayAdjustWheelEvent(
3829 aScrollContainerFrame, aEvent,
3830 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS_WITH_AUTO_DIR)) {
3831 aEvent->mOverflowDeltaY = aEvent->mDeltaY;
3832 }
3833 }
3834
3835 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", 3838
); MOZ_PretendNoReturn(); } } while (0)
3836 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", 3838
); MOZ_PretendNoReturn(); } } while (0)
3837 (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", 3838
); MOZ_PretendNoReturn(); } } while (0)
3838 "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", 3838
); MOZ_PretendNoReturn(); } } while (0)
;
3839 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", 3842
); MOZ_PretendNoReturn(); } } while (0)
3840 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", 3842
); MOZ_PretendNoReturn(); } } while (0)
3841 (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", 3842
); MOZ_PretendNoReturn(); } } while (0)
3842 "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", 3842
); MOZ_PretendNoReturn(); } } while (0)
;
3843
3844 WheelPrefs::GetInstance()->CancelApplyingUserPrefsFromOverflowDelta(aEvent);
3845}
3846
3847void EventStateManager::DecideGestureEvent(WidgetGestureNotifyEvent* aEvent,
3848 nsIFrame* targetFrame) {
3849 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"
, 3850); MOZ_PretendNoReturn(); } } while (0)
3850 "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"
, 3850); MOZ_PretendNoReturn(); } } while (0)
;
3851
3852 /* Check the ancestor tree to decide if any frame is willing* to receive
3853 * a MozPixelScroll event. If that's the case, the current touch gesture
3854 * will be used as a pan gesture; otherwise it will be a regular
3855 * mousedown/mousemove/click event.
3856 *
3857 * *willing: determine if it makes sense to pan the element using scroll
3858 * events:
3859 * - For web content: if there are any visible scrollbars on the touch point
3860 * - For XUL: if it's an scrollable element that can currently scroll in some
3861 * direction.
3862 *
3863 * Note: we'll have to one-off various cases to ensure a good usable behavior
3864 */
3865 WidgetGestureNotifyEvent::PanDirection panDirection =
3866 WidgetGestureNotifyEvent::ePanNone;
3867 bool displayPanFeedback = false;
3868 for (nsIFrame* current = targetFrame; current;
3869 current = nsLayoutUtils::GetCrossDocParentFrame(current)) {
3870 // e10s - mark remote content as pannable. This is a work around since
3871 // we don't have access to remote frame scroll info here. Apz data may
3872 // assist is solving this.
3873 if (current && IsTopLevelRemoteTarget(current->GetContent())) {
3874 panDirection = WidgetGestureNotifyEvent::ePanBoth;
3875 // We don't know when we reach bounds, so just disable feedback for now.
3876 displayPanFeedback = false;
3877 break;
3878 }
3879
3880 LayoutFrameType currentFrameType = current->Type();
3881
3882 // Scrollbars should always be draggable
3883 if (currentFrameType == LayoutFrameType::Scrollbar) {
3884 panDirection = WidgetGestureNotifyEvent::ePanNone;
3885 break;
3886 }
3887
3888 // Special check for trees
3889 if (nsTreeBodyFrame* treeFrame = do_QueryFrame(current)) {
3890 if (treeFrame->GetVerticalOverflow()) {
3891 panDirection = WidgetGestureNotifyEvent::ePanVertical;
3892 }
3893 break;
3894 }
3895
3896 if (ScrollContainerFrame* scrollContainerFrame = do_QueryFrame(current)) {
3897 layers::ScrollDirections scrollbarVisibility =
3898 scrollContainerFrame->GetScrollbarVisibility();
3899
3900 // Check if we have visible scrollbars
3901 if (scrollbarVisibility.contains(layers::ScrollDirection::eVertical)) {
3902 panDirection = WidgetGestureNotifyEvent::ePanVertical;
3903 displayPanFeedback = true;
3904 break;
3905 }
3906
3907 if (scrollbarVisibility.contains(layers::ScrollDirection::eHorizontal)) {
3908 panDirection = WidgetGestureNotifyEvent::ePanHorizontal;
3909 displayPanFeedback = true;
3910 }
3911 }
3912 } // ancestor chain
3913 aEvent->mDisplayPanFeedback = displayPanFeedback;
3914 aEvent->mPanDirection = panDirection;
3915}
3916
3917#ifdef XP_MACOSX
3918static nsINode* GetCrossDocParentNode(nsINode* aChild) {
3919 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",
3919); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ") ("
"The child is null!" ")"); do { MOZ_CrashSequence(__null, 3919
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3920 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", 3920
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3920); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3921
3922 nsINode* parent = aChild->GetParentNode();
3923 if (parent && parent->IsContent() && aChild->IsContent()) {
3924 parent = aChild->AsContent()->GetFlattenedTreeParent();
3925 }
3926
3927 if (parent || !aChild->IsDocument()) {
3928 return parent;
3929 }
3930
3931 return aChild->AsDocument()->GetEmbedderElement();
3932}
3933
3934static bool NodeAllowsClickThrough(nsINode* aNode) {
3935 while (aNode) {
3936 if (aNode->IsAnyOfXULElements(nsGkAtoms::browser, nsGkAtoms::tree)) {
3937 return false;
3938 }
3939 if (aNode->IsAnyOfXULElements(nsGkAtoms::scrollbar, nsGkAtoms::resizer)) {
3940 return true;
3941 }
3942 aNode = GetCrossDocParentNode(aNode);
3943 }
3944 return true;
3945}
3946#endif
3947
3948void EventStateManager::PostHandleKeyboardEvent(
3949 WidgetKeyboardEvent* aKeyboardEvent, nsIFrame* aTargetFrame,
3950 nsEventStatus& aStatus) {
3951 if (aStatus == nsEventStatus_eConsumeNoDefault) {
3952 return;
3953 }
3954
3955 RefPtr<nsPresContext> presContext = mPresContext;
3956
3957 if (!aKeyboardEvent->HasBeenPostedToRemoteProcess()) {
3958 if (aKeyboardEvent->IsWaitingReplyFromRemoteProcess()) {
3959 RefPtr<BrowserParent> remote =
3960 aTargetFrame ? BrowserParent::GetFrom(aTargetFrame->GetContent())
3961 : nullptr;
3962 if (remote) {
3963 // remote is null-checked above in order to let pre-existing event
3964 // targeting code's chrome vs. content decision override in case of
3965 // disagreement in order not to disrupt non-Fission e10s mode in case
3966 // there are still bugs in the Fission-mode code. That is, if remote
3967 // is nullptr, the pre-existing event targeting code has deemed this
3968 // event to belong to chrome rather than content.
3969 BrowserParent* preciseRemote = BrowserParent::GetFocused();
3970 if (preciseRemote) {
3971 remote = preciseRemote;
3972 }
3973 // else there was a race between layout and focus tracking
3974 }
3975 if (remote && !remote->IsReadyToHandleInputEvents()) {
3976 // We need to dispatch the event to the browser element again if we were
3977 // waiting for the key reply but the event wasn't sent to the content
3978 // process due to the remote browser wasn't ready.
3979 WidgetKeyboardEvent keyEvent(*aKeyboardEvent);
3980 aKeyboardEvent->MarkAsHandledInRemoteProcess();
3981 RefPtr<Element> ownerElement = remote->GetOwnerElement();
3982 EventDispatcher::Dispatch(ownerElement, presContext, &keyEvent);
3983 if (keyEvent.DefaultPrevented()) {
3984 aKeyboardEvent->PreventDefault(!keyEvent.DefaultPreventedByContent());
3985 aStatus = nsEventStatus_eConsumeNoDefault;
3986 return;
3987 }
3988 }
3989 }
3990 // The widget expects a reply for every keyboard event. If the event wasn't
3991 // dispatched to a content process (non-e10s or no content process
3992 // running), we need to short-circuit here. Otherwise, we need to wait for
3993 // the content process to handle the event.
3994 if (aKeyboardEvent->mWidget) {
3995 aKeyboardEvent->mWidget->PostHandleKeyEvent(aKeyboardEvent);
3996 }
3997 if (aKeyboardEvent->DefaultPrevented()) {
3998 aStatus = nsEventStatus_eConsumeNoDefault;
3999 return;
4000 }
4001 }
4002
4003 // XXX Currently, our automated tests don't support mKeyNameIndex.
4004 // Therefore, we still need to handle this with keyCode.
4005 switch (aKeyboardEvent->mKeyCode) {
4006 case NS_VK_TAB:
4007 case NS_VK_F6:
4008 // This is to prevent keyboard scrolling while alt modifier in use.
4009 if (!aKeyboardEvent->IsAlt()) {
4010 aStatus = nsEventStatus_eConsumeNoDefault;
4011
4012 // Handling the tab event after it was sent to content is bad,
4013 // because to the FocusManager the remote-browser looks like one
4014 // element, so we would just move the focus to the next element
4015 // in chrome, instead of handling it in content.
4016 if (aKeyboardEvent->HasBeenPostedToRemoteProcess()) {
4017 break;
4018 }
4019
4020 EnsureDocument(presContext);
4021 nsFocusManager* fm = nsFocusManager::GetFocusManager();
4022 if (fm && mDocument) {
4023 // Shift focus forward or back depending on shift key
4024 bool isDocMove = aKeyboardEvent->IsControl() ||
4025 aKeyboardEvent->mKeyCode == NS_VK_F6;
4026 uint32_t dir =
4027 aKeyboardEvent->IsShift()
4028 ? (isDocMove ? static_cast<uint32_t>(
4029 nsIFocusManager::MOVEFOCUS_BACKWARDDOC)
4030 : static_cast<uint32_t>(
4031 nsIFocusManager::MOVEFOCUS_BACKWARD))
4032 : (isDocMove ? static_cast<uint32_t>(
4033 nsIFocusManager::MOVEFOCUS_FORWARDDOC)
4034 : static_cast<uint32_t>(
4035 nsIFocusManager::MOVEFOCUS_FORWARD));
4036 RefPtr<Element> result;
4037 fm->MoveFocus(mDocument->GetWindow(), nullptr, dir,
4038 nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
4039 }
4040 }
4041 return;
4042 case 0:
4043 // We handle keys with no specific keycode value below.
4044 break;
4045 default:
4046 return;
4047 }
4048
4049 switch (aKeyboardEvent->mKeyNameIndex) {
4050 case KEY_NAME_INDEX_ZoomIn:
4051 case KEY_NAME_INDEX_ZoomOut:
4052 ChangeZoom(aKeyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_ZoomIn);
4053 aStatus = nsEventStatus_eConsumeNoDefault;
4054 break;
4055 default:
4056 break;
4057 }
4058}
4059
4060nsresult EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
4061 WidgetEvent* aEvent,
4062 nsIFrame* aTargetFrame,
4063 nsEventStatus* aStatus,
4064 nsIContent* aOverrideClickTarget) {
4065 AUTO_PROFILER_LABEL("EventStateManager::PostHandleEvent", DOM)mozilla::AutoProfilerLabel raiiObject4065( "EventStateManager::PostHandleEvent"
, nullptr, JS::ProfilingCategoryPair::DOM)
;
4066 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"
, 4066); return NS_ERROR_INVALID_ARG; } } while (false)
;
1
Assuming 'aPresContext' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
4067 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", 4067
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4
Assuming 'aStatus' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
4068
4069 mCurrentTarget = aTargetFrame;
4070 mCurrentTargetContent = nullptr;
4071
4072 HandleCrossProcessEvent(aEvent, aStatus);
4073 // NOTE: the above call may have destroyed aTargetFrame, please use
4074 // mCurrentTarget henceforth. This is to avoid using it accidentally:
4075 aTargetFrame = nullptr;
4076
4077 // Most of the events we handle below require a frame.
4078 // Add special cases here.
4079 if (!mCurrentTarget && aEvent->mMessage != eMouseUp &&
7
Assuming the condition is false
4080 aEvent->mMessage != eMouseDown && aEvent->mMessage != eDragEnter &&
4081 aEvent->mMessage != eDragOver && aEvent->mMessage != ePointerUp &&
4082 aEvent->mMessage != ePointerCancel) {
4083 return NS_OK;
4084 }
4085
4086 // Keep the prescontext alive, we might need it after event dispatch
4087 RefPtr<nsPresContext> presContext = aPresContext;
4088 nsresult ret = NS_OK;
4089
4090 switch (aEvent->mMessage) {
8
Control jumps to 'case ePointerUp:' at line 4284
4091 case eMouseDown: {
4092 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
4093 if (mouseEvent->mButton == MouseButton::ePrimary &&
4094 !sNormalLMouseEventInProcess) {
4095 // We got a mouseup event while a mousedown event was being processed.
4096 // Make sure that the capturing content is cleared.
4097 PresShell::ReleaseCapturingContent();
4098 break;
4099 }
4100
4101 // For remote content, capture the event in the parent process at the
4102 // <xul:browser remote> element. This will ensure that subsequent
4103 // mousemove/mouseup events will continue to be dispatched to this element
4104 // and therefore forwarded to the child.
4105 if (aEvent->HasBeenPostedToRemoteProcess() &&
4106 !PresShell::GetCapturingContent()) {
4107 if (nsIContent* content =
4108 mCurrentTarget ? mCurrentTarget->GetContent() : nullptr) {
4109 PresShell::SetCapturingContent(content, CaptureFlags::None, aEvent);
4110 } else {
4111 PresShell::ReleaseCapturingContent();
4112 }
4113 }
4114
4115 // If MouseEvent::PreventClickEvent() was called by chrome script,
4116 // we need to forget the clicking content and click count for the
4117 // following eMouseUp event.
4118 if (mouseEvent->mClickEventPrevented) {
4119 switch (mouseEvent->mButton) {
4120 case MouseButton::ePrimary:
4121 case MouseButton::eSecondary:
4122 case MouseButton::eMiddle: {
4123 GetLastMouseButtonPressInfo(mouseEvent->mButton).Clear();
4124 break;
4125 }
4126
4127 default:
4128 break;
4129 }
4130 }
4131
4132 nsCOMPtr<nsIContent> activeContent;
4133 // When content calls PreventDefault on pointerdown, we also call
4134 // PreventDefault on the subsequent mouse events to suppress default
4135 // behaviors. Normally, aStatus should be nsEventStatus_eConsumeNoDefault
4136 // when the event is DefaultPrevented but it's reset to
4137 // nsEventStatus_eIgnore in EventStateManager::PreHandleEvent. So we also
4138 // check if the event is DefaultPrevented.
4139 if (nsEventStatus_eConsumeNoDefault != *aStatus &&
4140 !aEvent->DefaultPrevented()) {
4141 RefPtr<Element> newFocus;
4142 bool suppressBlur = false;
4143 if (mCurrentTarget) {
4144 newFocus = Element::FromNodeOrNull(
4145 mCurrentTarget->GetEventTargetContent(aEvent));
4146 activeContent = mCurrentTarget->GetContent();
4147
4148 // In some cases, we do not want to even blur the current focused
4149 // element. Those cases are:
4150 // 1. -moz-user-focus CSS property is set to 'ignore';
4151 // 2. XUL control element has the disabled property set to 'true'.
4152 //
4153 // We can't use nsIFrame::IsFocusable() because we want to blur when
4154 // we click on a visibility: none element.
4155 // We can't use nsIContent::IsFocusable() because we want to blur when
4156 // we click on a non-focusable element like a <div>.
4157 // We have to use |aEvent->mTarget| to not make sure we do not check
4158 // an anonymous node of the targeted element.
4159 suppressBlur =
4160 mCurrentTarget->StyleUI()->UserFocus() == StyleUserFocus::Ignore;
4161
4162 if (!suppressBlur) {
4163 if (Element* element =
4164 Element::FromEventTargetOrNull(aEvent->mTarget)) {
4165 if (nsCOMPtr<nsIDOMXULControlElement> xulControl =
4166 element->AsXULControl()) {
4167 bool disabled = false;
4168 xulControl->GetDisabled(&disabled);
4169 suppressBlur = disabled;
4170 }
4171 }
4172 }
4173 }
4174
4175 // When a root content which isn't editable but has an editable HTML
4176 // <body> element is clicked, we should redirect the focus to the
4177 // the <body> element. E.g., when an user click bottom of the editor
4178 // where is outside of the <body> element, the <body> should be focused
4179 // and the user can edit immediately after that.
4180 //
4181 // NOTE: The newFocus isn't editable that also means it's not in
4182 // designMode. In designMode, all contents are not focusable.
4183 if (newFocus && !newFocus->IsEditable()) {
4184 Document* doc = newFocus->GetComposedDoc();
4185 if (doc && newFocus == doc->GetRootElement()) {
4186 Element* bodyElement =
4187 nsLayoutUtils::GetEditableRootContentByContentEditable(doc);
4188 if (bodyElement && bodyElement->GetPrimaryFrame()) {
4189 newFocus = bodyElement;
4190 }
4191 }
4192 }
4193
4194 // When the mouse is pressed, the default action is to focus the
4195 // target. Look for the nearest enclosing focusable frame.
4196 //
4197 // TODO: Probably this should be moved to Element::PostHandleEvent.
4198 for (; newFocus; newFocus = newFocus->GetFlattenedTreeParentElement()) {
4199 nsIFrame* frame = newFocus->GetPrimaryFrame();
4200 if (!frame) {
4201 continue;
4202 }
4203
4204 // If the mousedown happened inside a popup, don't try to set focus on
4205 // one of its containing elements
4206 if (frame->IsMenuPopupFrame()) {
4207 newFocus = nullptr;
4208 break;
4209 }
4210
4211 auto flags = IsFocusableFlags::WithMouse;
4212 if (frame->IsFocusable(flags)) {
4213 break;
4214 }
4215
4216 if (ShadowRoot* root = newFocus->GetShadowRoot()) {
4217 if (root->DelegatesFocus()) {
4218 if (Element* firstFocusable = root->GetFocusDelegate(flags)) {
4219 newFocus = firstFocusable;
4220 break;
4221 }
4222 }
4223 }
4224 }
4225
4226 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
4227 // if something was found to focus, focus it. Otherwise, if the
4228 // element that was clicked doesn't have -moz-user-focus: ignore,
4229 // clear the existing focus. For -moz-user-focus: ignore, the focus
4230 // is just left as is.
4231 // Another effect of mouse clicking, handled in Selection, is that
4232 // it should update the caret position to where the mouse was
4233 // clicked. Because the focus is cleared when clicking on a
4234 // non-focusable node, the next press of the tab key will cause
4235 // focus to be shifted from the caret position instead of the root.
4236 if (newFocus) {
4237 // use the mouse flag and the noscroll flag so that the content
4238 // doesn't unexpectedly scroll when clicking an element that is
4239 // only half visible
4240 uint32_t flags =
4241 nsIFocusManager::FLAG_BYMOUSE | nsIFocusManager::FLAG_NOSCROLL;
4242 // If this was a touch-generated event, pass that information:
4243 if (mouseEvent->mInputSource ==
4244 MouseEvent_Binding::MOZ_SOURCE_TOUCH) {
4245 flags |= nsIFocusManager::FLAG_BYTOUCH;
4246 }
4247 fm->SetFocus(newFocus, flags);
4248 } else if (!suppressBlur) {
4249 // clear the focus within the frame and then set it as the
4250 // focused frame
4251 EnsureDocument(mPresContext);
4252 if (mDocument) {
4253 nsCOMPtr<nsPIDOMWindowOuter> outerWindow = mDocument->GetWindow();
4254#ifdef XP_MACOSX
4255 if (!activeContent || !activeContent->IsXULElement())
4256#endif
4257 fm->ClearFocus(outerWindow);
4258 // Prevent switch frame if we're already not in the foreground tab
4259 // and we're in a content process.
4260 // TODO: If we were inactive frame in this tab, and now in
4261 // background tab, we shouldn't make the tab foreground, but
4262 // we should set focus to clicked document in the background
4263 // tab. However, nsFocusManager does not have proper method
4264 // for doing this. Therefore, we should skip setting focus
4265 // to clicked document for now.
4266 if (XRE_IsParentProcess() || IsInActiveTab(mDocument)) {
4267 fm->SetFocusedWindow(outerWindow);
4268 }
4269 }
4270 }
4271 }
4272
4273 // The rest is left button-specific.
4274 if (mouseEvent->mButton != MouseButton::ePrimary) {
4275 break;
4276 }
4277 } else {
4278 // if we're here, the event handler returned false, so stop
4279 // any of our own processing of a drag. Workaround for bug 43258.
4280 StopTrackingDragGesture(true);
4281 }
4282 } break;
4283 case ePointerCancel:
4284 case ePointerUp: {
4285 WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent();
4286 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"
, 4286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pointerEvent"
")"); do { MOZ_CrashSequence(__null, 4286); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9
Assuming 'pointerEvent' is non-null
10
Taking false branch
11
Loop condition is false. Exiting loop
4287 // Implicitly releasing capture for given pointer. ePointerLostCapture
4288 // should be send after ePointerUp or ePointerCancel.
4289 PointerEventHandler::ImplicitlyReleasePointerCapture(pointerEvent);
4290 PointerEventHandler::UpdatePointerActiveState(pointerEvent);
4291
4292 if (
14
Taking true branch
4293 // After pointercancel, pointer becomes invalid so we can remove
4294 // relevant helper from table.
4295 pointerEvent->mMessage == ePointerCancel ||
12
Assuming field 'mMessage' is not equal to ePointerCancel
4296 // pointerup for non-hoverable pointer needs to dispatch pointerout
4297 // and pointerleave events because the pointer is valid only while the
4298 // pointer is "down".
4299 !pointerEvent->InputSourceSupportsHover()) {
13
Assuming the condition is true
4300 GenerateMouseEnterExit(pointerEvent);
15
Calling 'EventStateManager::GenerateMouseEnterExit'
4301 mPointersEnterLeaveHelper.Remove(pointerEvent->pointerId);
4302 }
4303
4304 break;
4305 }
4306 case eMouseUp: {
4307 // We can unconditionally stop capturing because
4308 // we should never be capturing when the mouse button is up
4309 PresShell::ReleaseCapturingContent();
4310
4311 WidgetMouseEvent* mouseUpEvent = aEvent->AsMouseEvent();
4312 if (NeedsActiveContentChange(mouseUpEvent)) {
4313 ClearGlobalActiveContent(this);
4314 }
4315 if (mouseUpEvent) {
4316 if (EventCausesClickEvents(*mouseUpEvent)) {
4317 // Make sure to dispatch the click even if there is no frame for
4318 // the current target element. This is required for Web compatibility.
4319 RefPtr<EventStateManager> esm =
4320 ESMFromContentOrThis(aOverrideClickTarget);
4321 ret = esm->PostHandleMouseUp(mouseUpEvent, aStatus,
4322 aOverrideClickTarget);
4323 }
4324 switch (mouseUpEvent->mButton) {
4325 case MouseButton::ePrimary:
4326 case MouseButton::eSecondary:
4327 case MouseButton::eMiddle:
4328 GetLastMouseButtonPressInfo(mouseUpEvent->mButton).Clear();
4329 break;
4330 default:
4331 break;
4332 }
4333 }
4334
4335 // After dispatching click events for this eMouseUp, nobody needs to refer
4336 // to the preceding ePointerUp event target anymore because it was
4337 // required by the click event dispatcher to consider the target.
4338 // Therefore, PointerEventHandler should forget the target now.
4339 PointerEventHandler::ReleasePointerCapturingElementAtLastPointerUp();
4340
4341 if (PresShell* presShell = presContext->GetPresShell()) {
4342 RefPtr<nsFrameSelection> frameSelection = presShell->FrameSelection();
4343 frameSelection->SetDragState(false);
4344 }
4345 } break;
4346 case eContextMenu: {
4347 // If the context menu event was not prevented, a context menu is about
4348 // to be shown. Record a fallback time now so that pending event timing
4349 // entries (pointerdown, mousedown, etc.) are not inflated by the time
4350 // the user spends interacting with the menu.
4351 // https://github.com/w3c/event-timing/issues/154
4352 if (!aEvent->DefaultPrevented() && aEvent->IsTrusted()) {
4353 if (auto* perf = aPresContext->GetPerformanceMainThread()) {
4354 perf->RecordModalFallbackTime();
4355 }
4356 }
4357 break;
4358 }
4359 case eWheelOperationEnd: {
4360 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", 4360
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->IsTrusted()"
")"); do { MOZ_CrashSequence(__null, 4360); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4361 ScrollbarsForWheel::MayInactivate();
4362 WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent();
4363 ScrollContainerFrame* scrollTarget =
4364 ComputeScrollTargetAndMayAdjustWheelEvent(
4365 mCurrentTarget, wheelEvent,
4366 COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR);
4367 // If the wheel event was handled by APZ, APZ will perform the scroll
4368 // snap.
4369 if (scrollTarget && !WheelTransaction::HandledByApz()) {
4370 scrollTarget->ScrollSnap();
4371 }
4372 } break;
4373 case eWheel:
4374 case eWheelOperationStart: {
4375 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", 4375
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->IsTrusted()"
")"); do { MOZ_CrashSequence(__null, 4375); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4376
4377 if (*aStatus == nsEventStatus_eConsumeNoDefault) {
4378 ScrollbarsForWheel::Inactivate();
4379 break;
4380 }
4381
4382 WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent();
4383 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"
, 4383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wheelEvent"
")"); do { MOZ_CrashSequence(__null, 4383); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4384
4385 // When APZ is enabled, the actual scroll animation might be handled by
4386 // the compositor.
4387 WheelPrefs::Action action =
4388 wheelEvent->mFlags.mHandledByAPZ
4389 ? WheelPrefs::ACTION_NONE
4390 : WheelPrefs::GetInstance()->ComputeActionFor(wheelEvent);
4391
4392 WheelDeltaAdjustmentStrategy strategy =
4393 GetWheelDeltaAdjustmentStrategy(*wheelEvent);
4394 // Adjust the delta values of the wheel event if the current default
4395 // action is to horizontalize scrolling. I.e., deltaY values are set to
4396 // deltaX and deltaY and deltaZ values are set to 0.
4397 // If horizontalized, the delta values will be restored and its overflow
4398 // deltaX will become 0 when the WheelDeltaHorizontalizer instance is
4399 // being destroyed.
4400 WheelDeltaHorizontalizer horizontalizer(*wheelEvent);
4401 if (WheelDeltaAdjustmentStrategy::eHorizontalize == strategy) {
4402 horizontalizer.Horizontalize();
4403 }
4404
4405 // Since ComputeScrollTargetAndMayAdjustWheelEvent() may adjust the delta
4406 // if the event is auto-dir. So we use |ESMAutoDirWheelDeltaRestorer|
4407 // here.
4408 // An instance of |ESMAutoDirWheelDeltaRestorer| is used to monitor
4409 // auto-dir adjustment which may happen during its lifetime. If the delta
4410 // values is adjusted during its lifetime, the instance will restore the
4411 // adjusted delta when it's being destrcuted.
4412 ESMAutoDirWheelDeltaRestorer restorer(*wheelEvent);
4413 ScrollContainerFrame* scrollTarget =
4414 ComputeScrollTargetAndMayAdjustWheelEvent(
4415 mCurrentTarget, wheelEvent,
4416 COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR);
4417
4418 switch (action) {
4419 case WheelPrefs::ACTION_SCROLL:
4420 case WheelPrefs::ACTION_HORIZONTALIZED_SCROLL: {
4421 // For scrolling of default action, we should honor the mouse wheel
4422 // transaction.
4423
4424 ScrollbarsForWheel::PrepareToScrollText(this, mCurrentTarget,
4425 wheelEvent);
4426
4427 if (aEvent->mMessage != eWheel ||
4428 (!wheelEvent->mDeltaX && !wheelEvent->mDeltaY)) {
4429 break;
4430 }
4431
4432 ScrollbarsForWheel::SetActiveScrollTarget(scrollTarget);
4433
4434 ScrollContainerFrame* rootScrollContainerFrame =
4435 !mCurrentTarget
4436 ? nullptr
4437 : mCurrentTarget->PresShell()->GetRootScrollContainerFrame();
4438 if (!scrollTarget || scrollTarget == rootScrollContainerFrame) {
4439 wheelEvent->mViewPortIsOverscrolled = true;
4440 }
4441 wheelEvent->mOverflowDeltaX = wheelEvent->mDeltaX;
4442 wheelEvent->mOverflowDeltaY = wheelEvent->mDeltaY;
4443 WheelPrefs::GetInstance()->CancelApplyingUserPrefsFromOverflowDelta(
4444 wheelEvent);
4445 if (scrollTarget) {
4446 DoScrollText(scrollTarget, wheelEvent);
4447 } else {
4448 WheelTransaction::EndTransaction();
4449 ScrollbarsForWheel::Inactivate();
4450 }
4451 break;
4452 }
4453 case WheelPrefs::ACTION_HISTORY: {
4454 // If this event doesn't cause eLegacyMouseLineOrPageScroll event or
4455 // the direction is oblique, don't perform history back/forward.
4456 int32_t intDelta = wheelEvent->GetPreferredIntDelta();
4457 if (!intDelta) {
4458 break;
4459 }
4460 DoScrollHistory(intDelta);
4461 break;
4462 }
4463 case WheelPrefs::ACTION_ZOOM: {
4464 // If this event doesn't cause eLegacyMouseLineOrPageScroll event or
4465 // the direction is oblique, don't perform zoom in/out.
4466 int32_t intDelta = wheelEvent->GetPreferredIntDelta();
4467 if (!intDelta) {
4468 break;
4469 }
4470 DoScrollZoom(mCurrentTarget, intDelta);
4471 break;
4472 }
4473 case WheelPrefs::ACTION_NONE:
4474 default:
4475 bool allDeltaOverflown = false;
4476 if (wheelEvent->mDeltaX != 0.0 || wheelEvent->mDeltaY != 0.0) {
4477 if (scrollTarget) {
4478 WheelTransaction::WillHandleDefaultAction(
4479 wheelEvent, scrollTarget, mCurrentTarget);
4480 } else {
4481 WheelTransaction::EndTransaction();
4482 }
4483 }
4484 if (wheelEvent->mFlags.mHandledByAPZ) {
4485 if (wheelEvent->mCanTriggerSwipe) {
4486 // For events that can trigger swipes, APZ needs to know whether
4487 // scrolling is possible in the requested direction. It does this
4488 // by looking at the scroll overflow values on mCanTriggerSwipe
4489 // events after they have been processed. When determining if
4490 // a swipe should occur, we should not prefer the current wheel
4491 // transaction.
4492 nsIFrame* lastScrollFrame =
4493 WheelTransaction::GetScrollTargetFrame();
4494 bool wheelTransactionHandlesInput = false;
4495 if (lastScrollFrame) {
4496 ScrollContainerFrame* scrollContainerFrame =
4497 lastScrollFrame->GetScrollTargetFrame();
4498 if (scrollContainerFrame->IsRootScrollFrameOfDocument()) {
4499 // If the current wheel transaction target is the root scroll
4500 // frame and is not scrollable on the x-axis, all delta is
4501 // overflown and swipe-to-nav may occur.
4502 wheelTransactionHandlesInput = true;
4503 allDeltaOverflown = !WheelHandlingUtils::CanScrollOn(
4504 scrollContainerFrame, wheelEvent->mDeltaX, 0.0);
4505 } else if (WheelHandlingUtils::CanScrollOn(
4506 scrollContainerFrame, wheelEvent->mDeltaX,
4507 wheelEvent->mDeltaY)) {
4508 // If the current wheel transaction target is not the root
4509 // scroll frame, ensure that swipe to nav does not occur if
4510 // the scroll frame is scrollable on the x or y axis. If the
4511 // scroll frame cannot scroll, all delta _may_ be overflown.
4512 wheelTransactionHandlesInput = true;
4513 allDeltaOverflown = false;
4514 }
4515 }
4516 if (!wheelTransactionHandlesInput) {
4517 allDeltaOverflown = !ComputeScrollTarget(
4518 mCurrentTarget, wheelEvent,
4519 COMPUTE_DEFAULT_ACTION_TARGET_WITHOUT_WHEEL_TRANSACTION);
4520 }
4521 }
4522 } else {
4523 // The event was processed neither by APZ nor by us, so all of the
4524 // delta values must be overflown delta values.
4525 allDeltaOverflown = true;
4526 }
4527
4528 if (!allDeltaOverflown) {
4529 break;
4530 }
4531 wheelEvent->mOverflowDeltaX = wheelEvent->mDeltaX;
4532 wheelEvent->mOverflowDeltaY = wheelEvent->mDeltaY;
4533 WheelPrefs::GetInstance()->CancelApplyingUserPrefsFromOverflowDelta(
4534 wheelEvent);
4535 wheelEvent->mViewPortIsOverscrolled = true;
4536 break;
4537 }
4538 *aStatus = nsEventStatus_eConsumeNoDefault;
4539 } break;
4540
4541 case eGestureNotify: {
4542 if (nsEventStatus_eConsumeNoDefault != *aStatus) {
4543 DecideGestureEvent(aEvent->AsGestureNotifyEvent(), mCurrentTarget);
4544 }
4545 } break;
4546
4547 case eDragEnter:
4548 case eDragOver: {
4549 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", 4549
); MOZ_PretendNoReturn(); } } while (0)
;
4550
4551 // Check if the drag is occurring inside a scrollable area. If so, scroll
4552 // the area when the mouse is near the edges.
4553 if (mCurrentTarget && aEvent->mMessage == eDragOver) {
4554 nsIFrame* checkFrame = mCurrentTarget;
4555 while (checkFrame) {
4556 ScrollContainerFrame* scrollFrame = do_QueryFrame(checkFrame);
4557 // Break out so only the innermost scrollframe is scrolled.
4558 if (scrollFrame && scrollFrame->DragScroll(aEvent)) {
4559 break;
4560 }
4561 checkFrame = checkFrame->GetParent();
4562 }
4563 }
4564
4565 nsCOMPtr<nsIDragSession> dragSession =
4566 nsContentUtils::GetDragSession(mPresContext);
4567 if (!dragSession) break;
4568
4569 // Reset the flag.
4570 dragSession->SetOnlyChromeDrop(false);
4571 if (mPresContext) {
4572 EnsureDocument(mPresContext);
4573 }
4574 bool isChromeDoc = nsContentUtils::IsChromeDoc(mDocument);
4575
4576 // the initial dataTransfer is the one from the dragstart event that
4577 // was set on the dragSession when the drag began.
4578 RefPtr<DataTransfer> dataTransfer;
4579 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
4580
4581 WidgetDragEvent* dragEvent = aEvent->AsDragEvent();
4582
4583 // collect any changes to moz cursor settings stored in the event's
4584 // data transfer.
4585 UpdateDragDataTransfer(dragEvent);
4586
4587 // cancelling a dragenter or dragover event means that a drop should be
4588 // allowed, so update the dropEffect and the canDrop state to indicate
4589 // that a drag is allowed. If the event isn't cancelled, a drop won't be
4590 // allowed. Essentially, to allow a drop somewhere, specify the effects
4591 // using the effectAllowed and dropEffect properties in a dragenter or
4592 // dragover event and cancel the event. To not allow a drop somewhere,
4593 // don't cancel the event or set the effectAllowed or dropEffect to
4594 // "none". This way, if the event is just ignored, no drop will be
4595 // allowed.
4596 uint32_t dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
4597 uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE;
4598 if (nsEventStatus_eConsumeNoDefault == *aStatus) {
4599 // If the event has initialized its mDataTransfer, use it.
4600 // Or the event has not been initialized its mDataTransfer, but
4601 // it's set before dispatch because of synthesized, but without
4602 // testing session (e.g., emulating drag from another app), use it
4603 // coming from outside.
4604 // XXX Perhaps, for the latter case, we need new API because we don't
4605 // have a chance to initialize allowed effects of the session.
4606 if (dragEvent->mDataTransfer) {
4607 // get the dataTransfer and the dropEffect that was set on it
4608 dataTransfer = dragEvent->mDataTransfer;
4609 dropEffect = dataTransfer->DropEffectInt();
4610 } else {
4611 // if dragEvent->mDataTransfer is null, it means that no attempt was
4612 // made to access the dataTransfer during the event, yet the event
4613 // was cancelled. Instead, use the initial data transfer available
4614 // from the drag session. The drop effect would not have been
4615 // initialized (which is done in DragEvent::GetDataTransfer),
4616 // so set it from the drag action. We'll still want to filter it
4617 // based on the effectAllowed below.
4618 dataTransfer = initialDataTransfer;
4619
4620 dragSession->GetDragAction(&action);
4621
4622 // filter the drop effect based on the action. Use UNINITIALIZED as
4623 // any effect is allowed.
4624 dropEffect = nsContentUtils::FilterDropEffect(
4625 action, nsIDragService::DRAGDROP_ACTION_UNINITIALIZED);
4626 }
4627
4628 // At this point, if the dataTransfer is null, it means that the
4629 // drag was originally started by directly calling the drag service.
4630 // Just assume that all effects are allowed.
4631 uint32_t effectAllowed = nsIDragService::DRAGDROP_ACTION_UNINITIALIZED;
4632 if (dataTransfer) {
4633 effectAllowed = dataTransfer->EffectAllowedInt();
4634 }
4635
4636 // set the drag action based on the drop effect and effect allowed.
4637 // The drop effect field on the drag transfer object specifies the
4638 // desired current drop effect. However, it cannot be used if the
4639 // effectAllowed state doesn't include that type of action. If the
4640 // dropEffect is "none", then the action will be 'none' so a drop will
4641 // not be allowed.
4642 if (effectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED ||
4643 dropEffect & effectAllowed)
4644 action = dropEffect;
4645
4646 if (action == nsIDragService::DRAGDROP_ACTION_NONE)
4647 dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
4648
4649 // inform the drag session that a drop is allowed on this node.
4650 dragSession->SetDragAction(action);
4651 dragSession->SetCanDrop(action != nsIDragService::DRAGDROP_ACTION_NONE);
4652
4653 // For now, do this only for dragover.
4654 // XXXsmaug dragenter needs some more work.
4655 if (aEvent->mMessage == eDragOver && !isChromeDoc) {
4656 // Someone has called preventDefault(), check whether is was on
4657 // content or chrome.
4658 dragSession->SetOnlyChromeDrop(
4659 !dragEvent->mDefaultPreventedOnContent);
4660 }
4661 } else if (aEvent->mMessage == eDragOver && !isChromeDoc) {
4662 // No one called preventDefault(), so handle drop only in chrome.
4663 dragSession->SetOnlyChromeDrop(true);
4664 }
4665 if (auto* bc = BrowserChild::GetFrom(presContext->GetDocShell())) {
4666 bc->SendUpdateDropEffect(action, dropEffect);
4667 }
4668 if (aEvent->HasBeenPostedToRemoteProcess()) {
4669 dragSession->SetCanDrop(true);
4670 } else if (initialDataTransfer) {
4671 // Now set the drop effect in the initial dataTransfer. This ensures
4672 // that we can get the desired drop effect in the drop event. For events
4673 // dispatched to content, the content process will take care of setting
4674 // this.
4675 initialDataTransfer->SetDropEffectInt(dropEffect);
4676 }
4677 } break;
4678
4679 case eDrop: {
4680 if (aEvent->mFlags.mIsSynthesizedForTests) {
4681 nsCOMPtr<nsIDragService> dragService =
4682 do_GetService("@mozilla.org/widget/dragservice;1");
4683 nsCOMPtr<nsIDragSession> dragSession =
4684 nsContentUtils::GetDragSession(mPresContext);
4685 if (dragSession && dragService &&
4686 !dragService->GetNeverAllowSessionIsSynthesizedForTests()) {
4687 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", 4687
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dragSession->IsSynthesizedForTests()"
")"); do { MOZ_CrashSequence(__null, 4687); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4688 RefPtr<WindowContext> sourceWC;
4689 DebugOnly<nsresult> rvIgnored =
4690 dragSession->GetSourceWindowContext(getter_AddRefs(sourceWC));
4691 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"
, 4693); } } while (false)
4692 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"
, 4693); } } while (false)
4693 "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"
, 4693); } } while (false)
;
4694 // If the drag source hasn't been initialized, i.e., dragstart was
4695 // consumed by the test, the test needs to dispatch "dragend" event
4696 // instead of the drag session. Therefore, it does not make sense
4697 // to set drag end point in such case (you hit assersion if you do
4698 // it).
4699 if (sourceWC) {
4700 const CSSIntPoint dropPointInScreen = RoundedToInt(
4701 Event::GetScreenCoords(aPresContext, aEvent, aEvent->mRefPoint)
4702 .extract());
4703 dragSession->SetDragEndPointForTests(dropPointInScreen.x,
4704 dropPointInScreen.y);
4705 }
4706 }
4707 }
4708 sLastDragOverFrame = nullptr;
4709 ClearGlobalActiveContent(this);
4710 break;
4711 }
4712 case eDragExit: {
4713 // make sure to fire the enter and exit_synth events after the
4714 // eDragExit event, otherwise we'll clean up too early
4715 GenerateDragDropEnterExit(presContext, *aEvent->AsDragEvent());
4716 if (auto* bc = BrowserChild::GetFrom(presContext->GetDocShell())) {
4717 // SendUpdateDropEffect to prevent nsIDragService from waiting for
4718 // response of forwarded dragexit event.
4719 bc->SendUpdateDropEffect(nsIDragService::DRAGDROP_ACTION_NONE,
4720 nsIDragService::DRAGDROP_ACTION_NONE);
4721 }
4722 break;
4723 }
4724 case eKeyUp:
4725 // If space key is released, we need to inactivate the element which was
4726 // activated by preceding space key down.
4727 // XXX Currently, we don't store the reason of activation. Therefore,
4728 // this may cancel what is activated by a mousedown, but it must not
4729 // cause actual problem in web apps in the wild since it must be
4730 // rare case that users release space key during a mouse click/drag.
4731 if (aEvent->AsKeyboardEvent()->ShouldWorkAsSpaceKey()) {
4732 ClearGlobalActiveContent(this);
4733 }
4734 break;
4735
4736 case eKeyPress: {
4737 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
4738 PostHandleKeyboardEvent(keyEvent, mCurrentTarget, *aStatus);
4739 } break;
4740
4741 case eMouseEnterIntoWidget:
4742 if (mCurrentTarget) {
4743 nsCOMPtr<nsIContent> targetContent =
4744 mCurrentTarget->GetEventTargetContent(aEvent);
4745 SetContentState(targetContent, ElementState::HOVER);
4746 }
4747 break;
4748
4749 case eMouseExitFromWidget:
4750 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"
, 4751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Should've already been handled in PreHandleEvent()"
")"); do { MOZ_CrashSequence(__null, 4751); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4751 "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"
, 4751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Should've already been handled in PreHandleEvent()"
")"); do { MOZ_CrashSequence(__null, 4751); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4752 break;
4753
4754#ifdef XP_MACOSX
4755 case eMouseActivate:
4756 if (mCurrentTarget) {
4757 nsCOMPtr<nsIContent> targetContent =
4758 mCurrentTarget->GetExplicitEventTargetContent(aEvent);
4759 if (!NodeAllowsClickThrough(targetContent)) {
4760 *aStatus = nsEventStatus_eConsumeNoDefault;
4761 }
4762 }
4763 break;
4764#endif
4765
4766 default:
4767 break;
4768 }
4769
4770 // Reset target frame to null to avoid mistargeting after reentrant event
4771 mCurrentTarget = nullptr;
4772 mCurrentTargetContent = nullptr;
4773
4774 return ret;
4775}
4776
4777BrowserParent* EventStateManager::GetCrossProcessTarget() {
4778 return IMEStateManager::GetActiveBrowserParent();
4779}
4780
4781bool EventStateManager::IsTargetCrossProcess(WidgetGUIEvent* aEvent) {
4782 // Check to see if there is a focused, editable content in chrome,
4783 // in that case, do not forward IME events to content
4784 Element* focusedElement = GetFocusedElement();
4785 if (focusedElement && focusedElement->IsEditable()) {
4786 return false;
4787 }
4788 return IMEStateManager::GetActiveBrowserParent() != nullptr;
4789}
4790
4791void EventStateManager::NotifyDestroyPresContext(nsPresContext* aPresContext) {
4792 RefPtr<nsPresContext> presContext = aPresContext;
4793 if (presContext) {
4794 IMEStateManager::OnDestroyPresContext(*presContext);
4795 }
4796
4797 // Bug 70855: Presentation is going away, possibly for a reframe.
4798 // Reset the hover state so that if we're recreating the presentation,
4799 // we won't have the old hover state still set in the new presentation,
4800 // as if the new presentation is resized, a new element may be hovered.
4801 ResetHoverState();
4802
4803 mMouseEnterLeaveHelper = nullptr;
4804 mPointersEnterLeaveHelper.Clear();
4805 PointerEventHandler::NotifyDestroyPresContext(presContext);
4806}
4807
4808void EventStateManager::ResetHoverState() {
4809 if (mHoverContent) {
4810 SetContentState(nullptr, ElementState::HOVER);
4811 }
4812}
4813
4814void EventStateManager::SetPresContext(nsPresContext* aPresContext) {
4815 mPresContext = aPresContext;
4816}
4817
4818void EventStateManager::ClearFrameRefs(nsIFrame* aFrame) {
4819 if (!aFrame) {
4820 return;
4821 }
4822
4823 if (aFrame == mCurrentTarget) {
4824 mCurrentTargetContent = aFrame->GetContent();
4825 }
4826
4827 // If the element currently shown in the status bar has lost its
4828 // frame, clear the status bar.
4829 if (aFrame == mLinkOverFrame.GetFrame()) {
4830 nsIContent* content = aFrame->GetContent();
4831 if (content && content->IsElement()) {
4832 content->AsElement()->LeaveLink(mPresContext);
4833 }
4834 }
4835}
4836
4837struct CursorImage {
4838 gfx::IntPoint mHotspot;
4839 nsCOMPtr<imgIContainer> mContainer;
4840 ImageResolution mResolution;
4841 bool mEarlierCursorLoading = false;
4842};
4843
4844// Given the event that we're processing, and the computed cursor and hotspot,
4845// determine whether the custom CSS cursor should be blocked (that is, not
4846// honored).
4847//
4848// We will not honor it all of the following are true:
4849//
4850// * the size of the custom cursor is bigger than layout.cursor.block.max-size.
4851// * the bounds of the cursor would end up outside of the viewport of the
4852// top-level content document.
4853//
4854// This is done in order to prevent hijacking the cursor, see bug 1445844 and
4855// co.
4856static bool ShouldBlockCustomCursor(nsPresContext* aPresContext,
4857 WidgetEvent* aEvent,
4858 const CursorImage& aCursor) {
4859 int32_t width = 0;
4860 int32_t height = 0;
4861 aCursor.mContainer->GetWidth(&width);
4862 aCursor.mContainer->GetHeight(&height);
4863 aCursor.mResolution.ApplyTo(width, height);
4864
4865 int32_t maxSize = StaticPrefs::layout_cursor_block_max_size();
4866
4867 if (width <= maxSize && height <= maxSize) {
4868 return false;
4869 }
4870
4871 auto input = DOMIntersectionObserver::ComputeInput(*aPresContext->Document(),
4872 nullptr, nullptr, nullptr);
4873
4874 if (!input.mRootFrame) {
4875 return false;
4876 }
4877
4878 nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(
4879 aEvent, RelativeTo{input.mRootFrame});
4880
4881 // The cursor size won't be affected by our full zoom in the parent process,
4882 // so undo that before checking the rect.
4883 float zoom = aPresContext->GetFullZoom();
4884
4885 // Also adjust for accessibility cursor scaling factor.
4886 zoom /= LookAndFeel::GetFloat(LookAndFeel::FloatID::CursorScale, 1.0f);
4887
4888 nsSize size(CSSPixel::ToAppUnits(width / zoom),
4889 CSSPixel::ToAppUnits(height / zoom));
4890 nsPoint hotspot(
4891 CSSPixel::ToAppUnits(ViewAs<CSSPixel>(aCursor.mHotspot.x / zoom)),
4892 CSSPixel::ToAppUnits(ViewAs<CSSPixel>(aCursor.mHotspot.y / zoom)));
4893
4894 const nsRect cursorRect(point - hotspot, size);
4895 auto output = DOMIntersectionObserver::Intersect(input, cursorRect);
4896 return !output.mIntersectionRect ||
4897 !(*output.mIntersectionRect == cursorRect);
4898}
4899
4900static gfx::IntPoint ComputeHotspot(imgIContainer* aContainer,
4901 const Maybe<gfx::Point>& aHotspot) {
4902 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"
, 4902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContainer"
")"); do { MOZ_CrashSequence(__null, 4902); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4903
4904 // css3-ui says to use the CSS-specified hotspot if present,
4905 // otherwise use the intrinsic hotspot, otherwise use the top left
4906 // corner.
4907 if (aHotspot) {
4908 int32_t imgWidth, imgHeight;
4909 aContainer->GetWidth(&imgWidth);
4910 aContainer->GetHeight(&imgHeight);
4911 auto hotspot = gfx::IntPoint::Round(*aHotspot);
4912 return {std::max(std::min(hotspot.x.value, imgWidth - 1), 0),
4913 std::max(std::min(hotspot.y.value, imgHeight - 1), 0)};
4914 }
4915
4916 gfx::IntPoint hotspot;
4917 aContainer->GetHotspotX(&hotspot.x.value);
4918 aContainer->GetHotspotY(&hotspot.y.value);
4919 return hotspot;
4920}
4921
4922static CursorImage ComputeCustomCursor(nsPresContext* aPresContext,
4923 WidgetEvent* aEvent,
4924 const nsIFrame& aFrame,
4925 const nsIFrame::Cursor& aCursor) {
4926 if (aCursor.mAllowCustomCursor == nsIFrame::AllowCustomCursorImage::No) {
4927 return {};
4928 }
4929 const ComputedStyle& style =
4930 aCursor.mStyle ? *aCursor.mStyle : *aFrame.Style();
4931
4932 // If we are falling back because any cursor before us is loading, let the
4933 // consumer know.
4934 bool loading = false;
4935 for (const auto& image : style.StyleUI()->Cursor().images.AsSpan()) {
4936 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",
4937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "image.image.IsImageRequestType()"
") (" "Cursor image should only parse url() types" ")"); do {
MOZ_CrashSequence(__null, 4937); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4937 "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",
4937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "image.image.IsImageRequestType()"
") (" "Cursor image should only parse url() types" ")"); do {
MOZ_CrashSequence(__null, 4937); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4938 uint32_t status;
4939 imgRequestProxy* req = image.image.GetImageRequest();
4940 if (!req || NS_FAILED(req->GetImageStatus(&status))((bool)(__builtin_expect(!!(NS_FAILED_impl(req->GetImageStatus
(&status))), 0)))
) {
4941 continue;
4942 }
4943 if (!(status & imgIRequest::STATUS_LOAD_COMPLETE)) {
4944 loading = true;
4945 continue;
4946 }
4947 if (status & imgIRequest::STATUS_ERROR) {
4948 continue;
4949 }
4950 nsCOMPtr<imgIContainer> container;
4951 req->GetImage(getter_AddRefs(container));
4952 if (!container) {
4953 continue;
4954 }
4955 StyleImageOrientation orientation =
4956 aFrame.StyleVisibility()->UsedImageOrientation(req);
4957 container = nsLayoutUtils::OrientImage(container, orientation);
4958 Maybe<gfx::Point> specifiedHotspot =
4959 image.has_hotspot ? Some(gfx::Point{image.hotspot_x, image.hotspot_y})
4960 : Nothing();
4961 gfx::IntPoint hotspot = ComputeHotspot(container, specifiedHotspot);
4962 CursorImage result{hotspot, std::move(container),
4963 image.image.GetResolution(&style), loading};
4964 if (ShouldBlockCustomCursor(aPresContext, aEvent, result)) {
4965 continue;
4966 }
4967 // This is the one we want!
4968 return result;
4969 }
4970 return {{}, nullptr, {}, loading};
4971}
4972
4973void EventStateManager::UpdateCursor(nsPresContext* aPresContext,
4974 WidgetMouseEvent* aEvent,
4975 nsIFrame* aTargetFrame,
4976 nsEventStatus* aStatus) {
4977 if (!PointerEventHandler::IsLastPointerId(aEvent->pointerId)) {
4978 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)
4979 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)
4980 ("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)
4981 "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)
4982 "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)
4983 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)
4984 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)
4985 !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)
4986 ? "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)
4987 : 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)
4988 *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)
4989 .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)
4990 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)
;
4991 return;
4992 }
4993
4994 // XXX This is still not entirely correct, e.g. when mouse hover over the
4995 // broder of a cross-origin iframe, we should show the cursor specified on the
4996 // iframe (see bug 1943530).
4997 if (nsSubDocumentFrame* f = do_QueryFrame(aTargetFrame)) {
4998 if (auto* fl = f->FrameLoader();
4999 fl && fl->IsRemoteFrame() && f->ContentReactsToPointerEvents()) {
5000 // The sub-frame will update the cursor if needed.
5001 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)
5002 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)
5003 ("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)
5004 "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)
5005 "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)
5006 "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)
5007 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)
5008 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)
5009 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)
;
5010 return;
5011 }
5012 }
5013
5014 auto cursor = StyleCursorKind::Default;
5015 nsCOMPtr<imgIContainer> container;
5016 ImageResolution resolution;
5017 Maybe<gfx::IntPoint> hotspot;
5018
5019 if (mHidingCursorWhileTyping && aEvent->IsReal()) {
5020 // Any non-synthetic mouse event makes us show the cursor again.
5021 mHidingCursorWhileTyping = false;
5022 }
5023
5024 if (mHidingCursorWhileTyping) {
5025 cursor = StyleCursorKind::None;
5026 } else if (mLockCursor != kInvalidCursorKind) {
5027 // If cursor is locked just use the locked one
5028 cursor = mLockCursor;
5029 } else if (aTargetFrame) {
5030 // If not locked, look for correct cursor
5031 nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(
5032 aEvent, RelativeTo{aTargetFrame});
5033 const nsIFrame::Cursor framecursor = aTargetFrame->GetCursor(pt);
5034 const CursorImage customCursor =
5035 ComputeCustomCursor(aPresContext, aEvent, *aTargetFrame, framecursor);
5036
5037 // If the current cursor is from the same frame, and it is now
5038 // loading some new image for the cursor, we should wait for a
5039 // while rather than taking its fallback cursor directly.
5040 if (customCursor.mEarlierCursorLoading &&
5041 gLastCursorSourceFrame == aTargetFrame &&
5042 TimeStamp::NowLoRes() - gLastCursorUpdateTime <
5043 TimeDuration::FromMilliseconds(kCursorLoadingTimeout)) {
5044 return;
5045 }
5046 cursor = framecursor.mCursor;
5047 container = std::move(customCursor.mContainer);
5048 resolution = customCursor.mResolution;
5049 hotspot = Some(customCursor.mHotspot);
5050 }
5051
5052 if (aTargetFrame) {
5053 if (cursor == StyleCursorKind::Pointer && IsSelectingLink(aTargetFrame)) {
5054 cursor = aTargetFrame->GetWritingMode().IsVertical()
5055 ? StyleCursorKind::VerticalText
5056 : StyleCursorKind::Text;
5057 }
5058 SetCursor(cursor, container, resolution, hotspot,
5059 aTargetFrame->GetNearestWidget(), false);
5060 gLastCursorSourceFrame = aTargetFrame;
5061 gLastCursorUpdateTime = TimeStamp::NowLoRes();
5062 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
)
5063 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
)
5064 ("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
)
5065 "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
)
5066 "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
)
5067 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
)
5068 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
)
5069 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
)
;
5070 }
5071
5072 if (mLockCursor != kInvalidCursorKind || StyleCursorKind::Auto != cursor) {
5073 *aStatus = nsEventStatus_eConsumeDoDefault;
5074 }
5075}
5076
5077void EventStateManager::ClearCachedWidgetCursor(nsIFrame* aTargetFrame) {
5078 if (!aTargetFrame) {
5079 return;
5080 }
5081 nsIWidget* aWidget = aTargetFrame->GetNearestWidget();
5082 if (!aWidget) {
5083 return;
5084 }
5085 aWidget->ClearCachedCursor();
5086}
5087
5088void EventStateManager::StartHidingCursorWhileTyping(nsIWidget* aWidget) {
5089 if (mHidingCursorWhileTyping || sCursorSettingManager != this) {
5090 return;
5091 }
5092 mHidingCursorWhileTyping = true;
5093 SetCursor(StyleCursorKind::None, nullptr, {}, {}, aWidget, false);
5094}
5095
5096nsresult EventStateManager::SetCursor(StyleCursorKind aCursor,
5097 imgIContainer* aContainer,
5098 const ImageResolution& aResolution,
5099 const Maybe<gfx::IntPoint>& aHotspot,
5100 nsIWidget* aWidget, bool aLockCursor) {
5101 EnsureDocument(mPresContext);
5102 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", 5102
); return NS_ERROR_FAILURE; } } while (false)
;
5103 sCursorSettingManager = this;
5104
5105 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", 5105
); return NS_ERROR_FAILURE; } } while (false)
;
5106 if (aLockCursor) {
5107 if (StyleCursorKind::Auto != aCursor) {
5108 mLockCursor = aCursor;
5109 } else {
5110 // If cursor style is set to auto we unlock the cursor again.
5111 mLockCursor = kInvalidCursorKind;
5112 }
5113 }
5114 nsCursor c;
5115 switch (aCursor) {
5116 case StyleCursorKind::Auto:
5117 case StyleCursorKind::Default:
5118 c = eCursor_standard;
5119 break;
5120 case StyleCursorKind::Pointer:
5121 c = eCursor_hyperlink;
5122 break;
5123 case StyleCursorKind::Crosshair:
5124 c = eCursor_crosshair;
5125 break;
5126 case StyleCursorKind::Move:
5127 c = eCursor_move;
5128 break;
5129 case StyleCursorKind::Text:
5130 c = eCursor_select;
5131 break;
5132 case StyleCursorKind::Wait:
5133 c = eCursor_wait;
5134 break;
5135 case StyleCursorKind::Help:
5136 c = eCursor_help;
5137 break;
5138 case StyleCursorKind::NResize:
5139 c = eCursor_n_resize;
5140 break;
5141 case StyleCursorKind::SResize:
5142 c = eCursor_s_resize;
5143 break;
5144 case StyleCursorKind::WResize:
5145 c = eCursor_w_resize;
5146 break;
5147 case StyleCursorKind::EResize:
5148 c = eCursor_e_resize;
5149 break;
5150 case StyleCursorKind::NwResize:
5151 c = eCursor_nw_resize;
5152 break;
5153 case StyleCursorKind::SeResize:
5154 c = eCursor_se_resize;
5155 break;
5156 case StyleCursorKind::NeResize:
5157 c = eCursor_ne_resize;
5158 break;
5159 case StyleCursorKind::SwResize:
5160 c = eCursor_sw_resize;
5161 break;
5162 case StyleCursorKind::Copy: // CSS3
5163 c = eCursor_copy;
5164 break;
5165 case StyleCursorKind::Alias:
5166 c = eCursor_alias;
5167 break;
5168 case StyleCursorKind::ContextMenu:
5169 c = eCursor_context_menu;
5170 break;
5171 case StyleCursorKind::Cell:
5172 c = eCursor_cell;
5173 break;
5174 case StyleCursorKind::Grab:
5175 c = eCursor_grab;
5176 break;
5177 case StyleCursorKind::Grabbing:
5178 c = eCursor_grabbing;
5179 break;
5180 case StyleCursorKind::Progress:
5181 c = eCursor_spinning;
5182 break;
5183 case StyleCursorKind::ZoomIn:
5184 c = eCursor_zoom_in;
5185 break;
5186 case StyleCursorKind::ZoomOut:
5187 c = eCursor_zoom_out;
5188 break;
5189 case StyleCursorKind::NotAllowed:
5190 c = eCursor_not_allowed;
5191 break;
5192 case StyleCursorKind::ColResize:
5193 c = eCursor_col_resize;
5194 break;
5195 case StyleCursorKind::RowResize:
5196 c = eCursor_row_resize;
5197 break;
5198 case StyleCursorKind::NoDrop:
5199 c = eCursor_no_drop;
5200 break;
5201 case StyleCursorKind::VerticalText:
5202 c = eCursor_vertical_text;
5203 break;
5204 case StyleCursorKind::AllScroll:
5205 c = eCursor_all_scroll;
5206 break;
5207 case StyleCursorKind::NeswResize:
5208 c = eCursor_nesw_resize;
5209 break;
5210 case StyleCursorKind::NwseResize:
5211 c = eCursor_nwse_resize;
5212 break;
5213 case StyleCursorKind::NsResize:
5214 c = eCursor_ns_resize;
5215 break;
5216 case StyleCursorKind::EwResize:
5217 c = eCursor_ew_resize;
5218 break;
5219 case StyleCursorKind::None:
5220 c = eCursor_none;
5221 break;
5222 default:
5223 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"
, 5223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown cursor kind" ")"); do { MOZ_CrashSequence
(__null, 5223); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5224 c = eCursor_standard;
5225 break;
5226 }
5227
5228 uint32_t x = aHotspot ? aHotspot->x.value : 0;
5229 uint32_t y = aHotspot ? aHotspot->y.value : 0;
5230 aWidget->SetCursor(nsIWidget::Cursor{c, aContainer, x, y, aResolution});
5231 return NS_OK;
5232}
5233
5234bool EventStateManager::CursorSettingManagerHasLockedCursor() {
5235 return sCursorSettingManager &&
5236 sCursorSettingManager->mLockCursor != kInvalidCursorKind;
5237}
5238
5239class MOZ_STACK_CLASS ESMEventCB : public EventDispatchingCallback {
5240 public:
5241 explicit ESMEventCB(nsIContent* aTarget) : mTarget(aTarget) {}
5242
5243 MOZ_CAN_RUN_SCRIPT
5244 void HandleEvent(EventChainPostVisitor& aVisitor) override {
5245 if (aVisitor.mPresContext) {
5246 nsIFrame* frame = aVisitor.mPresContext->GetPrimaryFrameFor(mTarget);
5247 if (frame) {
5248 frame->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent->AsGUIEvent(),
5249 &aVisitor.mEventStatus);
5250 }
5251 }
5252 }
5253
5254 nsCOMPtr<nsIContent> mTarget;
5255};
5256
5257static UniquePtr<WidgetMouseEvent> CreateMouseOrPointerWidgetEvent(
5258 const WidgetMouseEvent* aMouseEvent, EventMessage aMessage,
5259 EventTarget* aRelatedTarget) {
5260 // This method does not support creating a mouse/pointer button change event
5261 // because of no data about the changing state.
5262 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", 5262
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage != eMouseDown"
")"); do { MOZ_CrashSequence(__null, 5262); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5263 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", 5263
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage != eMouseUp"
")"); do { MOZ_CrashSequence(__null, 5263); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5264 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", 5264
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage != ePointerDown"
")"); do { MOZ_CrashSequence(__null, 5264); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5265 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", 5265
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage != ePointerUp"
")"); do { MOZ_CrashSequence(__null, 5265); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5266 // This method is currently designed to create the following events.
5267 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", 5272
); 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, 5272); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5268 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", 5272
); 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, 5272); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5269 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", 5272
); 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, 5272); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5270 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", 5272
); 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, 5272); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5271 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", 5272
); 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, 5272); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5272 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", 5272
); 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, 5272); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5273
5274 UniquePtr<WidgetMouseEvent> newEvent;
5275 if (IsPointerEventMessage(aMessage)) {
5276 AUTO_PROFILER_LABEL("CreateMouseOrPointerWidgetEvent", OTHER)mozilla::AutoProfilerLabel raiiObject5276( "CreateMouseOrPointerWidgetEvent"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
5277
5278 newEvent = MakeUnique<WidgetPointerEvent>(aMouseEvent->IsTrusted(),
5279 aMessage, aMouseEvent->mWidget);
5280 if (const WidgetPointerEvent* const sourcePointerEvent =
5281 aMouseEvent->AsPointerEvent()) {
5282 WidgetPointerEvent* const newPointerEvent =
5283 static_cast<WidgetPointerEvent*>(newEvent.get());
5284 newPointerEvent->mIsPrimary = sourcePointerEvent->mIsPrimary;
5285 newPointerEvent->mWidth = sourcePointerEvent->mWidth;
5286 newPointerEvent->mHeight = sourcePointerEvent->mHeight;
5287 // Not assigning mFromTouchEvent
5288 }
5289 } else {
5290 newEvent = MakeUnique<WidgetMouseEvent>(aMouseEvent->IsTrusted(), aMessage,
5291 aMouseEvent->mWidget,
5292 WidgetMouseEvent::eReal);
5293 }
5294
5295 // Inherit whether the event is synthesized by the test API or not.
5296 // Then, when the event is synthesized by a test API and handled in a remote
5297 // process, it won't be ignored. See PresShell::HandleEvent().
5298 newEvent->mFlags.mIsSynthesizedForTests =
5299 aMouseEvent->mFlags.mIsSynthesizedForTests;
5300
5301 newEvent->mRelatedTarget = aRelatedTarget;
5302 newEvent->mRefPoint = aMouseEvent->mRefPoint;
5303 newEvent->mModifiers = aMouseEvent->mModifiers;
5304 newEvent->mInputSource = aMouseEvent->mInputSource;
5305 newEvent->pointerId = aMouseEvent->pointerId;
5306 // NOTE: If you need to change this if-expression, you need to update
5307 // WidgetMouseEventBase::ComputeMouseButtonPressure() too.
5308 if (!aMouseEvent->mFlags.mDispatchedAtLeastOnce &&
5309 aMouseEvent->InputSourceSupportsHover()) {
5310 // If we synthesize a pointer event or a mouse event from another event
5311 // which changes a button state whose input soucre supports hover state and
5312 // the source event has not been dispatched yet, we should set to the button
5313 // state of the synthesizing event to previous one.
5314 // Note that we don't need to do this if the input source does not support
5315 // hover state because a WPT check the behavior (see below) and the other
5316 // browsers pass the test even though this is inconsistent behavior.
5317 newEvent->mButton = newEvent->mClass == ePointerEventClass
5318 ? MouseButton::eNotPressed
5319 : MouseButton::ePrimary;
5320 // If the source event has not been dispatched into the DOM yet, we
5321 // need to remove the flag which is being pressed. Similarly, if the source
5322 // event has not been dispatched into the DOM yet, we need to add the flag
5323 // which is being released.
5324 newEvent->mButtons = aMouseEvent->ComputeButtonsBeforeDispatch();
5325 // Adjust pressure if it does not matches with mButtons.
5326 // FIXME: We may use wrong pressure value if the source event has not been
5327 // dispatched into the DOM yet. However, fixing this requires to store the
5328 // last pressure value somewhere (bug 1953669).
5329 newEvent->mPressure = newEvent->ComputeMouseButtonPressure();
5330 } else {
5331 // If the event has already been dispatched into the tree, web apps has
5332 // already handled the button state change, so the button state of the
5333 // source event has already synced.
5334 // If the input source does not have hover state, we don't need to modify
5335 // the state because the other browsers behave so and tested by
5336 // pointerevent_attributes_nohover_pointers.html even though this is
5337 // different expectation from
5338 // pointerevent_attributes_hoverable_pointers.html, but the other browsers
5339 // pass both of them.
5340 newEvent->mButton = aMouseEvent->mButton;
5341 newEvent->mButtons = aMouseEvent->mButtons;
5342 newEvent->mPressure = aMouseEvent->mPressure;
5343 }
5344 return newEvent;
5345}
5346
5347already_AddRefed<nsIWidget>
5348EventStateManager::DispatchMouseOrPointerBoundaryEvent(
5349 WidgetMouseEvent* aMouseEvent, EventMessage aMessage,
5350 nsIContent* aTargetContent, nsIContent* aRelatedContent) {
5351 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", 5354
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
")"); do { MOZ_CrashSequence(__null, 5354); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
59
Taking false branch
5352 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", 5354
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
")"); do { MOZ_CrashSequence(__null, 5354); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5353 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", 5354
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
")"); do { MOZ_CrashSequence(__null, 5354); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5354 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", 5354
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
")"); do { MOZ_CrashSequence(__null, 5354); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5355
5356 // https://w3c.github.io/pointerlock/#dom-element-requestpointerlock
5357 // "[Once in the locked state...E]vents that require the concept
5358 // of a mouse cursor must not be dispatched (for example: mouseover,
5359 // mouseout...).
5360 // XXXedgar should we also block pointer events?
5361 if (PointerLockManager::IsLocked() &&
60
Loop condition is false. Exiting loop
61
Assuming the condition is true
62
Taking true branch
5362 (aMessage
61.1
'aMessage' is not equal to eMouseLeave
== eMouseLeave || aMessage
61.2
'aMessage' is not equal to eMouseEnter
== eMouseEnter ||
5363 aMessage
61.3
'aMessage' is not equal to eMouseOver
== eMouseOver || aMessage
61.4
'aMessage' is equal to eMouseOut
== eMouseOut)) {
5364 mCurrentTargetContent = nullptr;
5365 nsCOMPtr<Element> pointerLockedElement =
5366 PointerLockManager::GetLockedElement();
5367 if (!pointerLockedElement) {
63
Taking false branch
5368 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"
, 5368)
;
5369 return nullptr;
5370 }
5371 nsIFrame* const pointerLockedFrame =
64
'pointerLockedFrame' initialized here
5372 mPresContext->GetPrimaryFrameFor(pointerLockedElement);
5373 if (NS_WARN_IF(!pointerLockedFrame)NS_warn_if_impl(!pointerLockedFrame, "!pointerLockedFrame", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5373)
) {
65
Assuming 'pointerLockedFrame' is null
66
Assuming the condition is false
67
Taking false branch
5374 return nullptr;
5375 }
5376 return do_AddRef(pointerLockedFrame->GetNearestWidget());
68
Called C++ object pointer is null
5377 }
5378
5379 mCurrentTargetContent = nullptr;
5380
5381 if (!aTargetContent) {
5382 return nullptr;
5383 }
5384
5385 // Store the widget before dispatching the event because some event listeners
5386 // of the dispatching event may cause reframe the target or remove the target
5387 // from the tree.
5388 nsCOMPtr<nsIWidget> targetWidget;
5389 if (nsIFrame* const targetFrame =
5390 mPresContext->GetPrimaryFrameFor(aTargetContent)) {
5391 targetWidget = targetFrame->GetNearestWidget();
5392 }
5393
5394 nsCOMPtr<nsIContent> targetContent = aTargetContent;
5395 nsCOMPtr<nsIContent> relatedContent = aRelatedContent;
5396
5397 UniquePtr<WidgetMouseEvent> dispatchEvent =
5398 CreateMouseOrPointerWidgetEvent(aMouseEvent, aMessage, relatedContent);
5399
5400 AutoWeakFrame previousTarget = mCurrentTarget;
5401 mCurrentTargetContent = targetContent;
5402
5403 nsEventStatus status = nsEventStatus_eIgnore;
5404 ESMEventCB callback(targetContent);
5405 RefPtr<nsPresContext> presContext = mPresContext;
5406 EventDispatcher::Dispatch(targetContent, presContext, dispatchEvent.get(),
5407 nullptr, &status, &callback);
5408
5409 if (mPresContext) {
5410 // If we are entering/leaving remote content, dispatch a mouse enter/exit
5411 // event to the remote frame.
5412 if (IsTopLevelRemoteTarget(targetContent)) {
5413 if (aMessage == eMouseOut) {
5414 // For remote content, send a puppet widget mouse exit event.
5415 UniquePtr<WidgetMouseEvent> remoteEvent =
5416 CreateMouseOrPointerWidgetEvent(aMouseEvent, eMouseExitFromWidget,
5417 relatedContent);
5418 remoteEvent->mExitFrom = Some(WidgetMouseEvent::ePuppet);
5419
5420 // mCurrentTarget is set to the new target, so we must reset it to the
5421 // old target and then dispatch a cross-process event. (mCurrentTarget
5422 // will be set back below.) HandleCrossProcessEvent will query for the
5423 // proper target via GetEventTarget which will return mCurrentTarget.
5424 mCurrentTarget = mPresContext->GetPrimaryFrameFor(targetContent);
5425 HandleCrossProcessEvent(remoteEvent.get(), &status);
5426 } else if (aMessage == eMouseOver) {
5427 UniquePtr<WidgetMouseEvent> remoteEvent =
5428 CreateMouseOrPointerWidgetEvent(aMouseEvent, eMouseEnterIntoWidget,
5429 relatedContent);
5430 HandleCrossProcessEvent(remoteEvent.get(), &status);
5431 }
5432 }
5433 }
5434
5435 mCurrentTargetContent = nullptr;
5436 mCurrentTarget = previousTarget;
5437
5438 return targetWidget.forget();
5439}
5440
5441static nsIContent* FindCommonAncestor(nsIContent* aNode1, nsIContent* aNode2) {
5442 if (!aNode1 || !aNode2) {
5443 return nullptr;
5444 }
5445 return nsContentUtils::GetCommonFlattenedTreeAncestor(aNode1, aNode2);
5446}
5447
5448class EnterLeaveDispatcher {
5449 public:
5450 EnterLeaveDispatcher(EventStateManager* aESM, nsIContent* aTarget,
5451 nsIContent* aRelatedTarget,
5452 WidgetMouseEvent* aMouseEvent,
5453 EventMessage aEventMessage)
5454 : mESM(aESM), mMouseEvent(aMouseEvent), mEventMessage(aEventMessage) {
5455 nsPIDOMWindowInner* win =
5456 aTarget ? aTarget->OwnerDoc()->GetInnerWindow() : nullptr;
5457 if (aMouseEvent->AsPointerEvent()
5458 ? win && win->HasPointerEnterLeaveEventListeners()
5459 : win && win->HasMouseEnterLeaveEventListeners()) {
5460 mRelatedTarget =
5461 aRelatedTarget ? aRelatedTarget->FindFirstNonChromeOnlyAccessContent()
5462 : nullptr;
5463 nsINode* commonParent = FindCommonAncestor(aTarget, aRelatedTarget);
5464 nsIContent* current = aTarget;
5465 // Note, it is ok if commonParent is null!
5466 while (current && current != commonParent) {
5467 if (!current->ChromeOnlyAccess()) {
5468 mTargets.AppendObject(current);
5469 }
5470 // mouseenter/leave is fired only on elements.
5471 current = current->GetFlattenedTreeParent();
5472 }
5473 }
5474 }
5475
5476 // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
5477 MOZ_CAN_RUN_SCRIPT_BOUNDARY void Dispatch() {
5478 if (mEventMessage == eMouseEnter || mEventMessage == ePointerEnter) {
5479 for (int32_t i = mTargets.Count() - 1; i >= 0; --i) {
5480 nsCOMPtr<nsIWidget> widget = mESM->DispatchMouseOrPointerBoundaryEvent(
5481 mMouseEvent, mEventMessage, MOZ_KnownLive(mTargets[i])(mTargets[i]),
5482 mRelatedTarget);
5483 }
5484 } else {
5485 for (int32_t i = 0; i < mTargets.Count(); ++i) {
5486 nsCOMPtr<nsIWidget> widget = mESM->DispatchMouseOrPointerBoundaryEvent(
5487 mMouseEvent, mEventMessage, MOZ_KnownLive(mTargets[i])(mTargets[i]),
5488 mRelatedTarget);
5489 }
5490 }
5491 }
5492
5493 // Nothing overwrites anything after constructor. Please remove MOZ_KnownLive
5494 // and MOZ_KNOWN_LIVE if anything marked as such becomes mutable.
5495 const RefPtr<EventStateManager> mESM;
5496 nsCOMArray<nsIContent> mTargets;
5497 MOZ_KNOWN_LIVE nsCOMPtr<nsIContent> mRelatedTarget;
5498 WidgetMouseEvent* mMouseEvent;
5499 EventMessage mEventMessage;
5500};
5501
5502void EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
5503 nsIContent* aMovingInto) {
5504 const bool isPointer = aMouseEvent->mClass == ePointerEventClass;
20
Assuming field 'mClass' is not equal to ePointerEventClass
39
Assuming field 'mClass' is not equal to ePointerEventClass
5505 LogModule* const logModule =
5506 isPointer
20.1
'isPointer' is false
39.1
'isPointer' is false
? sPointerBoundaryLog : sMouseBoundaryLog;
21
'?' condition is false
40
'?' condition is false
5507
5508 RefPtr<OverOutElementsWrapper> wrapper = GetWrapperByEventID(aMouseEvent);
5509
5510 // If there is no deepest "leave" event target, that means the last "over"
5511 // target has already been removed from the tree. Therefore, checking only
5512 // the "leave" event target is enough.
5513 if (!wrapper || !wrapper->GetDeepestLeaveEventTarget()) {
22
Assuming the condition is false
23
Taking false branch
41
Assuming the condition is false
42
Taking false branch
5514 return;
5515 }
5516 // Before firing "out" and/or "leave" events, check for recursion
5517 if (wrapper->IsDispatchingOutEventOnLastOverEventTarget()) {
24
Taking false branch
43
Taking false branch
5518 return;
5519 }
5520
5521 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
5522 ("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)
5523 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)
5524 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)
;
5525
5526 // XXX If a content node is a container of remove content, it should be
5527 // replaced with them and its children should not be visible. Therefore,
5528 // if the deepest "enter" target is not the last "over" target, i.e., the
5529 // last "over" target has been removed from the DOM tree, it means that the
5530 // child/descendant was not replaced by remote content. So,
5531 // wrapper->GetOutEventTaget() may be enough here.
5532 if (RefPtr<nsFrameLoaderOwner> flo =
29
Taking true branch
48
Taking false branch
5533 do_QueryObject(wrapper->GetDeepestLeaveEventTarget())) {
5534 if (BrowsingContext* bc = flo->GetExtantBrowsingContext()) {
30
Assuming 'bc' is non-null
31
Taking true branch
5535 if (nsIDocShell* docshell = bc->GetDocShell()) {
32
Assuming 'docshell' is non-null
33
Taking true branch
5536 if (RefPtr<nsPresContext> presContext = docshell->GetPresContext()) {
34
Taking true branch
5537 EventStateManager* kidESM = presContext->EventStateManager();
5538 // Not moving into any element in this subdocument
5539 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
5540 ("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)
5541 "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)
5542 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)
;
5543 kidESM->NotifyMouseOut(aMouseEvent, nullptr);
38
Calling 'EventStateManager::NotifyMouseOut'
5544 }
5545 }
5546 }
5547 }
5548 // That could have caused DOM events which could wreak havoc. Reverify
5549 // things and be careful.
5550 if (!wrapper->GetDeepestLeaveEventTarget()) {
49
Taking false branch
5551 return;
5552 }
5553
5554 wrapper->WillDispatchOutAndOrLeaveEvent();
5555
5556 // Don't touch hover state if aMovingInto is non-null. Caller will update
5557 // hover state itself, and we have optimizations for hover switching between
5558 // two nearby elements both deep in the DOM tree that would be defeated by
5559 // switching the hover state to null here.
5560 if (!aMovingInto
49.1
'aMovingInto' is null
&& (!isPointer
49.2
'isPointer' is false
|| aMouseEvent->InputSourceSupportsHover())) {
5561 // Unset :hover
5562 SetContentState(nullptr, ElementState::HOVER);
5563 }
5564
5565 EnterLeaveDispatcher leaveDispatcher(
5566 this, wrapper->GetDeepestLeaveEventTarget(), aMovingInto, aMouseEvent,
5567 isPointer
49.3
'isPointer' is false
? ePointerLeave : eMouseLeave);
50
'?' condition is false
5568
5569 // "out" events hould be fired only when the deepest "leave" event target
5570 // is the last "over" event target.
5571 if (nsCOMPtr<nsIContent> outEventTarget = wrapper->GetOutEventTarget()) {
51
Taking true branch
5572 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
5573 ("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)
5574 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)
5575 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)
5576 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)
;
5577 nsCOMPtr<nsIWidget> widget = DispatchMouseOrPointerBoundaryEvent(
58
Calling 'EventStateManager::DispatchMouseOrPointerBoundaryEvent'
5578 aMouseEvent, isPointer
56.1
'isPointer' is false
? ePointerOut : eMouseOut, outEventTarget,
57
'?' condition is false
5579 aMovingInto);
5580 }
5581
5582 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)
5583 ("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)
5584 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)
5585 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)
5586 ? 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)
5587 : "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)
5588 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)
;
5589 leaveDispatcher.Dispatch();
5590
5591 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)
5592 ("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)
;
5593 wrapper->DidDispatchOutAndOrLeaveEvent();
5594}
5595
5596void EventStateManager::RecomputeMouseEnterStateForRemoteFrame(
5597 Element& aElement) {
5598 if (!mMouseEnterLeaveHelper ||
5599 mMouseEnterLeaveHelper->GetDeepestLeaveEventTarget() != &aElement) {
5600 return;
5601 }
5602
5603 if (BrowserParent* remote = BrowserParent::GetFrom(&aElement)) {
5604 remote->MouseEnterIntoWidget();
5605 }
5606}
5607
5608void EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
5609 nsIContent* aContent) {
5610 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"
, 5610); MOZ_PretendNoReturn(); } } while (0)
;
5611
5612 const bool isPointer = aMouseEvent->mClass == ePointerEventClass;
5613 LogModule* const logModule =
5614 isPointer ? sPointerBoundaryLog : sMouseBoundaryLog;
5615
5616 RefPtr<OverOutElementsWrapper> wrapper = GetWrapperByEventID(aMouseEvent);
5617
5618 // If we have next "out" event target and it's the new "over" target, we don't
5619 // need to dispatch "out" nor "enter" event.
5620 if (!wrapper || aContent == wrapper->GetOutEventTarget()) {
5621 return;
5622 }
5623
5624 // Before firing "over" and "enter" events, check for recursion
5625 if (wrapper->IsDispatchingOverEventOn(aContent)) {
5626 return;
5627 }
5628
5629 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)
5630 ("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)
5631 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)
5632 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)
;
5633
5634 // Check to see if we're a subdocument and if so update the parent
5635 // document's ESM state to indicate that the mouse is over the
5636 // content associated with our subdocument.
5637 EnsureDocument(mPresContext);
5638 if (Document* parentDoc = mDocument->GetInProcessParentDocument()) {
5639 if (nsCOMPtr<nsIContent> docContent = mDocument->GetEmbedderElement()) {
5640 if (PresShell* parentPresShell = parentDoc->GetPresShell()) {
5641 RefPtr<EventStateManager> parentESM =
5642 parentPresShell->GetPresContext()->EventStateManager();
5643 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)
5644 ("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)
5645 "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)
5646 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)
;
5647 parentESM->NotifyMouseOver(aMouseEvent, docContent);
5648 }
5649 }
5650 }
5651 // Firing the DOM event in the parent document could cause all kinds
5652 // of havoc. Reverify and take care.
5653 if (aContent == wrapper->GetOutEventTarget()) {
5654 return;
5655 }
5656
5657 // Remember the deepest leave event target as the related content for the
5658 // DispatchMouseOrPointerBoundaryEvent() call below, since NotifyMouseOut()
5659 // resets it, bug 298477.
5660 nsCOMPtr<nsIContent> deepestLeaveEventTarget =
5661 wrapper->GetDeepestLeaveEventTarget();
5662
5663 EnterLeaveDispatcher enterDispatcher(this, aContent, deepestLeaveEventTarget,
5664 aMouseEvent,
5665 isPointer ? ePointerEnter : eMouseEnter);
5666
5667 if (!isPointer || aMouseEvent->InputSourceSupportsHover()) {
5668 SetContentState(aContent, ElementState::HOVER);
5669 }
5670
5671 NotifyMouseOut(aMouseEvent, aContent);
5672
5673 wrapper->WillDispatchOverAndEnterEvent(aContent);
5674
5675 // Fire mouseover
5676 // XXX If aContent has already been removed from the DOM tree, what should we
5677 // do? At least, dispatching `mouseover` on it is odd.
5678 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)
5679 ("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)
5680 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)
5681 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)
;
5682 nsCOMPtr<nsIWidget> targetWidget = DispatchMouseOrPointerBoundaryEvent(
5683 aMouseEvent, isPointer ? ePointerOver : eMouseOver, aContent,
5684 deepestLeaveEventTarget);
5685
5686 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)
5687 ("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)
5688 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)
5689 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)
;
5690 enterDispatcher.Dispatch();
5691
5692 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)
5693 ("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)
5694 "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)
5695 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)
;
5696 wrapper->DidDispatchOverAndEnterEvent(
5697 aContent->GetComposedDoc() == mDocument ? aContent : nullptr,
5698 targetWidget);
5699}
5700
5701// Returns the size and also the center point of the window's client area. The
5702// center point is in widget coordinates, i.e. relative to the widget's top-left
5703// corner, not in screen coordinates, the same units that UIEvent:: refpoint is
5704// in. It may not be the exact center of the window if the platform requires
5705// rounding the coordinate.
5706static std::pair<LayoutDeviceIntSize, LayoutDeviceIntPoint>
5707GetWindowClientSizeAndCenterPoint(nsIWidget* aWidget) {
5708 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"
, 5708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 5708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5709
5710 LayoutDeviceIntSize size = aWidget->GetClientSize();
5711 LayoutDeviceIntPoint point(size.width / 2, size.height / 2);
5712 int32_t round = aWidget->RoundsWidgetCoordinatesTo();
5713 point.x = point.x / round * round;
5714 point.y = point.y / round * round;
5715 return std::pair{size, point};
5716}
5717
5718void EventStateManager::GeneratePointerEnterExit(EventMessage aMessage,
5719 WidgetMouseEvent* aEvent) {
5720 WidgetPointerEvent pointerEvent =
5721 WidgetPointerEvent::MakeCopyFromMouseEvent(*aEvent);
5722 pointerEvent.mMessage = aMessage;
5723 GenerateMouseEnterExit(&pointerEvent);
5724}
5725
5726/* static */
5727void EventStateManager::UpdateLastRefPointOfMouseEvent(
5728 WidgetMouseEvent* aMouseEvent) {
5729 if (aMouseEvent->mMessage != ePointerRawUpdate &&
5730 aMouseEvent->mMessage != eMouseMove &&
5731 aMouseEvent->mMessage != ePointerMove) {
5732 return;
5733 }
5734
5735 const LayoutDeviceIntPoint& lastRefPoint =
5736 aMouseEvent->mMessage == ePointerRawUpdate ? sLastRefPointOfRawUpdate
5737 : sLastRefPoint;
5738
5739 // Mouse movement is reported on the MouseEvent.movement{X,Y} fields.
5740 // Movement is calculated in UIEvent::GetMovementPoint() as:
5741 // previous_mousemove_mRefPoint - current_mousemove_mRefPoint.
5742 //
5743 // When the pref is enabled, not every mousemove event causes a synthetic
5744 // re-centering event to be dispatched, so we should not forcibly set
5745 // mLastRefPoint to the center point.
5746 if (PointerLockManager::ShouldResetPointer() && aMouseEvent->mWidget &&
5747 !StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled()) {
5748 // The pointer is locked. If the pointer is not located at the center of
5749 // the window, dispatch a synthetic mousemove to return the pointer there.
5750 // Doing this between "real" pointer moves gives the impression that the
5751 // (locked) pointer can continue moving and won't stop at the screen
5752 // boundary. We cancel the synthetic event so that we don't end up
5753 // dispatching the centering move event to content.
5754 aMouseEvent->mLastRefPoint =
5755 GetWindowClientSizeAndCenterPoint(aMouseEvent->mWidget).second;
5756
5757 } else if (lastRefPoint == kInvalidRefPoint) {
5758 // We don't have a valid previous mousemove mRefPoint. This is either
5759 // the first move we've encountered, or the mouse has just re-entered
5760 // the application window. We should report (0,0) movement for this
5761 // case, so make the current and previous mRefPoints the same.
5762 aMouseEvent->mLastRefPoint = aMouseEvent->mRefPoint;
5763 } else {
5764 aMouseEvent->mLastRefPoint = lastRefPoint;
5765 }
5766
5767 if (auto coalescedEvents = aMouseEvent->mCoalescedWidgetEvents) {
5768 // Fix up mLastRefPoints of coalesced events, so that each one's
5769 // movementX/Y is relative to the last.
5770 WidgetPointerEvent* prev = nullptr;
5771 for (WidgetPointerEvent& coalesced : coalescedEvents->mEvents) {
5772 coalesced.mLastRefPoint =
5773 prev ? prev->mRefPoint : aMouseEvent->mLastRefPoint;
5774 prev = &coalesced;
5775 }
5776 }
5777}
5778
5779/* static */
5780void EventStateManager::RequestLockPointer(nsIWidget* aWidget,
5781 nsPresContext* aPresContext,
5782 bool aUnadjustedMovement) {
5783 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"
, 5783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 5783); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5784 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"
, 5784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
")"); do { MOZ_CrashSequence(__null, 5784); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5785
5786 if (!PointerLockManager::ShouldResetPointer()) {
5787 return;
5788 }
5789
5790 // When the dom.pointer-lock.reset-to-center-from-parent pref is enabled,
5791 // resetting pointer should only happen in the parent process.
5792 MOZ_ASSERT_IF(do { if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled
()) { 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", 5794
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5794); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5793 StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled(),do { if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled
()) { 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", 5794
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5794); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5794 XRE_IsParentProcess())do { if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled
()) { 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", 5794
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5794); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5795 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", 5795
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sPreLockScreenPoint == kInvalidRefPoint"
")"); do { MOZ_CrashSequence(__null, 5795); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5796 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", 5796
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sSynthCenteringPoint == kInvalidRefPoint"
")"); do { MOZ_CrashSequence(__null, 5796); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5797
5798 // Activate native pointer lock on platforms where it is required.
5799 aWidget->LockNativePointer(aUnadjustedMovement
5800 ? nsIWidget::NativePointerLockMode::Unadjusted
5801 : nsIWidget::NativePointerLockMode::Regular);
5802
5803 // Store the last known ref point so we can reposition the pointer after
5804 // unlock.
5805 sPreLockScreenPoint = LayoutDeviceIntPoint::Round(
5806 sLastScreenPoint * aPresContext->CSSToDevPixelScale());
5807
5808 // Fire a synthetic mouse move to ensure event state is updated. We first
5809 // set the mouse to the center of the window, so that the mouse event
5810 // doesn't report any movement.
5811 sLastRefPoint = sLastRefPointOfRawUpdate =
5812 GetWindowClientSizeAndCenterPoint(aWidget).second;
5813
5814 // Only do this when repositioning happens in the parent process, so we don't
5815 // change the original behavior.
5816 if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled()) {
5817 sSynthCenteringPoint = sLastRefPoint;
5818 }
5819
5820 aWidget->SynthesizeNativeMouseMove(
5821 sLastRefPoint + aWidget->WidgetToScreenOffset(), nullptr);
5822}
5823
5824/* static */
5825void EventStateManager::ResetPointerToWindowCenterWhilePointerLocked(
5826 WidgetMouseEvent* aMouseEvent) {
5827 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"
, 5827); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseEvent"
")"); do { MOZ_CrashSequence(__null, 5827); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5828
5829 if (!PointerLockManager::ShouldResetPointer()) {
5830 return;
5831 }
5832
5833 // When the dom.pointer-lock.reset-to-center-from-parent pref is enabled,
5834 // pointer repositioning should be triggered from the parent process.
5835 MOZ_ASSERT_IF(do { if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled
()) { 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", 5837
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5837); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5836 StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled(),do { if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled
()) { 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", 5837
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5837); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5837 XRE_IsParentProcess())do { if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled
()) { 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", 5837
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5837); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5838
5839 if ((aMouseEvent->mMessage != ePointerRawUpdate &&
5840 aMouseEvent->mMessage != eMouseMove &&
5841 aMouseEvent->mMessage != ePointerMove) ||
5842 !aMouseEvent->mWidget || !aMouseEvent->IsReal()) {
5843 return;
5844 }
5845
5846 // We generate pointermove from mousemove event, so only synthesize native
5847 // mouse move and update sSynthCenteringPoint by mousemove event.
5848 const bool updateSynthCenteringPoint = aMouseEvent->mMessage == eMouseMove;
5849 const auto recenteringPoint = [&]() -> Maybe<LayoutDeviceIntPoint> {
5850 if (!updateSynthCenteringPoint) {
5851 return Nothing();
5852 }
5853
5854 auto [size, center] =
5855 GetWindowClientSizeAndCenterPoint(aMouseEvent->mWidget);
5856 if (!StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled()) {
5857 if (aMouseEvent->mRefPoint != center) {
5858 return Some(center);
5859 }
5860 return Nothing();
5861 }
5862
5863 // The pointer cannot be move outside the browser window boundary, as each
5864 // platform now use a native API to "lock" the pointer Therefore, we do not
5865 // need to reposition it to the center on every mousemove event. However, we
5866 // still need to recenter it once it moves too close the the boundary;
5867 // otherwise, the pointer may become stuck at the boundary and no longer be
5868 // able to move in certain directions. The boundary buffer is currently
5869 // 25% of the window size.
5870 LayoutDeviceIntRect rect(size.Width() / 4, size.Height() / 4,
5871 size.Width() / 2, size.Height() / 2);
5872 if (!rect.Contains(aMouseEvent->mRefPoint)) {
5873 return Some(center);
5874 }
5875 return Nothing();
5876 }();
5877
5878 // The pointer is locked. If the pointer is not located at the center of
5879 // the window, dispatch a synthetic mousemove to return the pointer there.
5880 // Doing this between "real" pointer moves gives the impression that the
5881 // (locked) pointer can continue moving and won't stop at the screen
5882 // boundary. We cancel the synthetic event so that we don't end up
5883 // dispatching the centering move event to content.
5884 if (recenteringPoint) {
5885 // Mouse move doesn't finish at the center of the window. Dispatch a
5886 // synthetic native mouse event to move the pointer back to the center
5887 // of the window, to faciliate more movement. But first, record that
5888 // we've dispatched a synthetic mouse movement, so we can cancel it
5889 // in the other branch here.
5890 sSynthCenteringPoint = *recenteringPoint;
5891
5892 // XXX Once we fix XXX comments in SetPointerLock about this API, we could
5893 // restrict that this API works only in the automation mode or in the
5894 // pointer locked situation.
5895 aMouseEvent->mWidget->SynthesizeNativeMouseMove(
5896 sSynthCenteringPoint + aMouseEvent->mWidget->WidgetToScreenOffset(),
5897 nullptr);
5898 return;
5899 }
5900
5901 if (!StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled()) {
5902 if (aMouseEvent->mRefPoint == sSynthCenteringPoint) {
5903 // This is the "synthetic native" event we dispatched to re-center the
5904 // pointer. Cancel it so we don't expose the centering move to content.
5905 aMouseEvent->StopPropagation();
5906 // Clear sSynthCenteringPoint so we don't cancel other events
5907 // targeted at the center.
5908 if (updateSynthCenteringPoint) {
5909 sSynthCenteringPoint = kInvalidRefPoint;
5910 }
5911 }
5912 return;
5913 }
5914
5915 // The synthesized re-centering event might be coalesced with subsequent
5916 // events at the OS level, so the event's ref point might not exactly match
5917 // sSynthCenteringPoint here.
5918 if (sSynthCenteringPoint != kInvalidRefPoint) {
5919 // If the synthesized re-centering even is coalesced, we need to report the
5920 // corresponding movement if the OS does not provide movement data. The
5921 // synthesized re-centering event is also very important for content process
5922 // to update its last ref point, so it should not be compressed or
5923 // coalesced, setting movement data can also prevent it from being
5924 // compressed or coalesced.
5925 if (!aMouseEvent->mMovement) {
5926 aMouseEvent->mMovement.emplace(aMouseEvent->mRefPoint -
5927 sSynthCenteringPoint);
5928 }
5929
5930 // This is the "synthetic native" event we dispatched to re-center the
5931 // pointer. We don't expose it to content. We also want to propagate this
5932 // state to the content process, so we do not use `StopPropagation()`, since
5933 // that state is reset for each event group.
5934 if (*aMouseEvent->mMovement == LayoutDeviceIntPoint(0, 0)) {
5935 aMouseEvent->mFlags.mOnlySystemGroupDispatch = true;
5936 }
5937
5938 // Clear sSynthCenteringPoint so subsequent events are handled normally.
5939 if (updateSynthCenteringPoint) {
5940 sSynthCenteringPoint = kInvalidRefPoint;
5941 }
5942 }
5943}
5944
5945/* static */
5946void EventStateManager::ReleaseLockedPointer(nsIWidget* aWidget) {
5947 if (sPreLockScreenPoint == kInvalidRefPoint) {
5948 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", 5948
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sSynthCenteringPoint == kInvalidRefPoint"
")"); do { MOZ_CrashSequence(__null, 5948); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5949 return;
5950 }
5951
5952 // When the dom.pointer-lock.reset-to-center-from-parent pref is enabled,
5953 // resetting pointer should only happen in the parent process.
5954 MOZ_ASSERT_IF(do { if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled
()) { 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", 5956
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5956); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5955 StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled(),do { if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled
()) { 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", 5956
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5956); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5956 XRE_IsParentProcess())do { if (StaticPrefs::dom_pointer_lock_reset_to_center_from_parent_enabled
()) { 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", 5956
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5956); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5957
5958 // Reset sSynthCenteringPoint to invalid so that next time we start
5959 // locking pointer, it has its initial value.
5960 sSynthCenteringPoint = kInvalidRefPoint;
5961
5962 LayoutDeviceIntPoint preLockScreenPoint = sPreLockScreenPoint;
5963 sPreLockScreenPoint = kInvalidRefPoint;
5964
5965 if (aWidget) {
5966 // Deactivate native pointer lock on platforms where it is required
5967 aWidget->UnlockNativePointer();
5968
5969 // Unlocking, so return pointer to the original position by firing a
5970 // synthetic mouse event. We first reset sLastRefPoint and
5971 // sLastRefPointOfRawUpdate to its pre-pointerlock position, so that the
5972 // synthetic mouse event reports no movement.
5973 sLastRefPoint = sLastRefPointOfRawUpdate =
5974 preLockScreenPoint - aWidget->WidgetToScreenOffset();
5975
5976 aWidget->SynthesizeNativeMouseMove(preLockScreenPoint, nullptr);
5977 }
5978}
5979
5980/* static */
5981void EventStateManager::UpdateLastPointerPosition(
5982 WidgetMouseEvent* aMouseEvent) {
5983 if (aMouseEvent->IsSynthesized()) {
5984 return;
5985 }
5986 if (aMouseEvent->mMessage == eMouseMove) {
5987 sLastRefPoint = aMouseEvent->mRefPoint;
5988 } else if (aMouseEvent->mMessage == ePointerRawUpdate ||
5989 // FYI: ePointerRawUpdate is handled only when there are some
5990 // `pointerrawupdate` event listeners. Therefore, we need to
5991 // update the last ref point for ePointerRawUpdate when we dispatch
5992 // ePointerMove too since the first `pointerrawupdate` event
5993 // listener may be added after the ePointerMove.
5994 aMouseEvent->mMessage == ePointerMove) {
5995 // XXX Shouldn't we store last refpoint of PointerEvent per pointerId?
5996 sLastRefPointOfRawUpdate = aMouseEvent->mRefPoint;
5997 }
5998}
5999
6000void EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent) {
6001 EnsureDocument(mPresContext);
6002 if (!mDocument) return;
16
Taking false branch
6003
6004 // Hold onto old target content through the event and reset after.
6005 nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
6006
6007 switch (aMouseEvent->mMessage) {
17
Control jumps to 'case eMouseExitFromWidget:' at line 6064
6008 case eMouseMove:
6009 case ePointerMove:
6010 case ePointerRawUpdate:
6011 case ePointerDown:
6012 case ePointerGotCapture: {
6013 // Get the target content target (mousemove target == mouseover target)
6014 nsCOMPtr<nsIContent> targetElement =
6015 GetExplicitEventTargetContent(aMouseEvent);
6016 if (!targetElement) {
6017 // We're always over the document root, even if we're only
6018 // over dead space in a page (whose frame is not associated with
6019 // any content) or in print preview dead space
6020 targetElement = mDocument->GetRootElement();
6021 }
6022 if (targetElement) {
6023 NotifyMouseOver(aMouseEvent, targetElement);
6024 }
6025 break;
6026 }
6027 case ePointerUp: {
6028 if (aMouseEvent->mFlags.mDispatchedAtLeastOnce) {
6029 // If we've already dispatched the pointerup event caused by
6030 // non-hoverable input device like touch, we need to synthesize
6031 // pointerout and pointerleave events because the poiner is valid only
6032 // while it's "down".
6033 if (!aMouseEvent->InputSourceSupportsHover()) {
6034 NotifyMouseOut(aMouseEvent, nullptr);
6035 }
6036 break;
6037 }
6038
6039 // If we're going to dispatch the pointerup event and the element under
6040 // the pointer is changed from the previous pointer event dispatching, we
6041 // need to dispatch pointer boundary events. If the pointing device is
6042 // hoverable, we always need to do it. Otherwise, an element captures the
6043 // pointer by default. If so, we don't need the boundary events, but if
6044 // the capture has already been released, e.g., by the capturing element
6045 // is removed, we need to dispatch the pointer boundary event the same
6046 // way as with hoverable pointer.
6047 if (aMouseEvent->InputSourceSupportsHover() ||
6048 !PointerEventHandler::GetPointerCapturingElement(
6049 aMouseEvent->pointerId)) {
6050 nsCOMPtr<nsIContent> targetElement =
6051 GetExplicitEventTargetContent(aMouseEvent);
6052 if (!targetElement) {
6053 targetElement = mDocument->GetRootElement();
6054 }
6055 if (targetElement) {
6056 NotifyMouseOver(aMouseEvent, targetElement);
6057 }
6058 break;
6059 }
6060 break;
6061 }
6062 case ePointerLeave:
6063 case ePointerCancel:
6064 case eMouseExitFromWidget: {
6065 // This is actually the window mouse exit or pointer leave event. We're
6066 // not moving into any new element.
6067
6068 RefPtr<OverOutElementsWrapper> helper = GetWrapperByEventID(aMouseEvent);
6069 if (helper) {
18
Taking false branch
6070 nsCOMPtr<nsIWidget> lastOverWidget = helper->GetLastOverWidget();
6071 if (lastOverWidget &&
6072 nsContentUtils::GetTopLevelWidget(aMouseEvent->mWidget) !=
6073 nsContentUtils::GetTopLevelWidget(lastOverWidget)) {
6074 // the Mouse/PointerOut event widget doesn't have same top widget with
6075 // the last over event target, it's a spurious event for the frame for
6076 // the target.
6077 break;
6078 }
6079 }
6080
6081 // Reset sLastRefPoint and sLastRefPointOfRawUpdate, so that we'll know
6082 // not to report any movement the next time we re-enter the window.
6083 sLastRefPoint = sLastRefPointOfRawUpdate = kInvalidRefPoint;
6084
6085 NotifyMouseOut(aMouseEvent, nullptr);
19
Calling 'EventStateManager::NotifyMouseOut'
6086 break;
6087 }
6088 default:
6089 break;
6090 }
6091
6092 // reset mCurretTargetContent to what it was
6093 mCurrentTargetContent = std::move(targetBeforeEvent);
6094}
6095
6096OverOutElementsWrapper* EventStateManager::GetWrapperByEventID(
6097 WidgetMouseEvent* aMouseEvent) {
6098 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"
, 6098); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseEvent"
")"); do { MOZ_CrashSequence(__null, 6098); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6099 WidgetPointerEvent* pointer = aMouseEvent->AsPointerEvent();
6100 if (!pointer) {
6101 if (!mMouseEnterLeaveHelper) {
6102 mMouseEnterLeaveHelper = new OverOutElementsWrapper(
6103 OverOutElementsWrapper::BoundaryEventType::Mouse);
6104 }
6105 return mMouseEnterLeaveHelper;
6106 }
6107 return mPointersEnterLeaveHelper.GetOrInsertNew(
6108 pointer->pointerId, OverOutElementsWrapper::BoundaryEventType::Pointer);
6109}
6110
6111/* static */
6112void EventStateManager::SetPointerLock(nsIWidget* aWidget,
6113 nsPresContext* aPresContext,
6114 bool aUnadjustedMovement) {
6115 // Reset mouse wheel transaction
6116 WheelTransaction::EndTransaction();
6117
6118 // Deal with DnD events
6119 nsCOMPtr<nsIDragService> dragService =
6120 do_GetService("@mozilla.org/widget/dragservice;1");
6121
6122 if (PointerLockManager::IsLocked()) {
6123 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",
6123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ") ("
"Locking pointer requires a widget" ")"); do { MOZ_CrashSequence
(__null, 6123); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6124 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"
, 6124); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
") (" "Locking pointer requires a presContext" ")"); do { MOZ_CrashSequence
(__null, 6124); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6125
6126 // Release all pointer capture when a pointer lock is successfully applied
6127 // on an element.
6128 PointerEventHandler::ReleaseAllPointerCapture();
6129
6130 // Suppress DnD
6131 if (dragService) {
6132 dragService->Suppress();
6133 }
6134
6135 RequestLockPointer(aWidget, aPresContext, aUnadjustedMovement);
6136 } else {
6137 ReleaseLockedPointer(aWidget);
6138
6139 // Unsuppress DnD
6140 if (dragService) {
6141 dragService->Unsuppress();
6142 }
6143 }
6144}
6145
6146void EventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext,
6147 WidgetDragEvent& aDragEvent) {
6148 // Hold onto old target content through the event and reset after.
6149 nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
6150
6151 switch (aDragEvent.mMessage) {
6152 case eDragOver: {
6153 // when dragging from one frame to another, events are fired in the
6154 // order: dragexit, dragenter, dragleave
6155 if (sLastDragOverFrame != mCurrentTarget) {
6156 // We'll need the content, too, to check if it changed separately from
6157 // the frames.
6158 nsCOMPtr<nsIContent> lastContent;
6159 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", 6160
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragExit) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6160); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6160 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", 6160
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragExit) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6160); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6161 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", 6162
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragEnter) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6162); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6162 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", 6162
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragEnter) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6162); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6163 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", 6164
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragLeave) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6164); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6164 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", 6164
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragLeave) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6164); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6165 nsCOMPtr<nsIContent> targetContent =
6166 mCurrentTarget->GetEventTargetContent(aDragEvent);
6167 if (sLastDragOverFrame) {
6168 // The frame has changed but the content may not have. Check before
6169 // dispatching to content
6170 lastContent = sLastDragOverFrame->GetEventTargetContent(aDragEvent);
6171 RefPtr<nsPresContext> presContext = sLastDragOverFrame->PresContext();
6172 FireDragEnterOrExit(presContext, aDragEvent, eDragExit, targetContent,
6173 lastContent, sLastDragOverFrame);
6174 nsIContent* target = sLastDragOverFrame
6175 ? sLastDragOverFrame.GetFrame()->GetContent()
6176 : nullptr;
6177 // XXXedgar, look like we need to consider fission OOP iframe, too.
6178 if (IsTopLevelRemoteTarget(target)) {
6179 // Dragging something and moving from web content to chrome only
6180 // fires dragexit and dragleave to xul:browser. We have to forward
6181 // dragexit to sLastDragOverFrame when its content is a remote
6182 // target. We don't forward dragleave since it's generated from
6183 // dragexit.
6184 WidgetDragEvent remoteEvent(aDragEvent.IsTrusted(), eDragExit,
6185 aDragEvent.mWidget);
6186 remoteEvent.AssignDragEventData(aDragEvent, true);
6187 remoteEvent.mFlags.mIsSynthesizedForTests =
6188 aDragEvent.mFlags.mIsSynthesizedForTests;
6189 nsEventStatus remoteStatus = nsEventStatus_eIgnore;
6190 HandleCrossProcessEvent(&remoteEvent, &remoteStatus);
6191 }
6192 }
6193
6194 AutoWeakFrame currentTraget = mCurrentTarget;
6195 FireDragEnterOrExit(aPresContext, aDragEvent, eDragEnter, lastContent,
6196 targetContent, currentTraget);
6197
6198 if (sLastDragOverFrame) {
6199 RefPtr<nsPresContext> presContext = sLastDragOverFrame->PresContext();
6200 FireDragEnterOrExit(presContext, aDragEvent, eDragLeave,
6201 targetContent, lastContent, sLastDragOverFrame);
6202 }
6203
6204 sLastDragOverFrame = mCurrentTarget;
6205 }
6206 } break;
6207
6208 case eDragExit: {
6209 // This is actually the window mouse exit event.
6210 if (sLastDragOverFrame) {
6211 nsCOMPtr<nsIContent> lastContent =
6212 sLastDragOverFrame->GetEventTargetContent(aDragEvent);
6213 RefPtr<nsPresContext> lastDragOverFramePresContext =
6214 sLastDragOverFrame->PresContext();
6215 FireDragEnterOrExit(lastDragOverFramePresContext, aDragEvent, eDragExit,
6216 nullptr, lastContent, sLastDragOverFrame);
6217 FireDragEnterOrExit(lastDragOverFramePresContext, aDragEvent,
6218 eDragLeave, nullptr, lastContent,
6219 sLastDragOverFrame);
6220
6221 sLastDragOverFrame = nullptr;
6222 }
6223 } break;
6224
6225 default:
6226 break;
6227 }
6228
6229 // reset mCurretTargetContent to what it was
6230 mCurrentTargetContent = std::move(targetBeforeEvent);
6231
6232 // Now flush all pending notifications, for better responsiveness.
6233 FlushLayout(aPresContext);
6234}
6235
6236void EventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext,
6237 const WidgetDragEvent& aDragEvent,
6238 EventMessage aMessage,
6239 nsIContent* aRelatedTarget,
6240 nsIContent* aTargetContent,
6241 AutoWeakFrame& aTargetFrame) {
6242 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", 6243
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eDragLeave || aMessage == eDragExit || aMessage == eDragEnter"
")"); do { MOZ_CrashSequence(__null, 6243); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6243 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", 6243
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eDragLeave || aMessage == eDragExit || aMessage == eDragEnter"
")"); do { MOZ_CrashSequence(__null, 6243); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6244 nsEventStatus status = nsEventStatus_eIgnore;
6245 WidgetDragEvent event(aDragEvent.IsTrusted(), aMessage, aDragEvent.mWidget);
6246 event.AssignDragEventData(aDragEvent, false);
6247 event.mFlags.mIsSynthesizedForTests =
6248 aDragEvent.mFlags.mIsSynthesizedForTests;
6249 event.mRelatedTarget = aRelatedTarget;
6250 if (aMessage == eDragExit && !StaticPrefs::dom_event_dragexit_enabled()) {
6251 event.mFlags.mOnlyChromeDispatch = true;
6252 }
6253
6254 mCurrentTargetContent = aTargetContent;
6255
6256 if (aTargetContent != aRelatedTarget) {
6257 // XXX This event should still go somewhere!!
6258 if (aTargetContent) {
6259 EventDispatcher::Dispatch(aTargetContent, aPresContext, &event, nullptr,
6260 &status);
6261 }
6262
6263 // adjust the drag hover if the dragenter event was cancelled or this is a
6264 // drag exit
6265 if (status == nsEventStatus_eConsumeNoDefault || aMessage == eDragExit) {
6266 SetContentState((aMessage == eDragEnter) ? aTargetContent : nullptr,
6267 ElementState::DRAGOVER);
6268 }
6269
6270 // collect any changes to moz cursor settings stored in the event's
6271 // data transfer.
6272 UpdateDragDataTransfer(&event);
6273 }
6274
6275 // Finally dispatch the event to the frame
6276 if (aTargetFrame) {
6277 aTargetFrame->HandleEvent(aPresContext, &event, &status);
6278 }
6279}
6280
6281void EventStateManager::UpdateDragDataTransfer(WidgetDragEvent* dragEvent) {
6282 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"
, 6282); MOZ_PretendNoReturn(); } } while (0)
;
6283 if (!dragEvent->mDataTransfer) {
6284 return;
6285 }
6286
6287 nsCOMPtr<nsIDragSession> dragSession =
6288 nsContentUtils::GetDragSession(mPresContext);
6289
6290 if (dragSession) {
6291 // the initial dataTransfer is the one from the dragstart event that
6292 // was set on the dragSession when the drag began.
6293 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
6294 if (initialDataTransfer) {
6295 // retrieve the current moz cursor setting and save it.
6296 nsAutoString mozCursor;
6297 dragEvent->mDataTransfer->GetMozCursor(mozCursor);
6298 initialDataTransfer->SetMozCursor(mozCursor);
6299 }
6300 }
6301}
6302
6303void EventStateManager::PrepareForFollowingClickEvent(
6304 WidgetMouseEvent& aEvent, nsIContent* aOverrideClickTarget) {
6305 const nsCOMPtr<nsIContent> mouseContent =
6306 aOverrideClickTarget
6307 ? aOverrideClickTarget->GetInclusiveFlattenedTreeAncestorElement()
6308 : (mCurrentTarget ? mCurrentTarget->GetEventTargetContent(aEvent)
6309 : nullptr);
6310 LastMouseButtonPressInfo& lastButtonPressInfo =
6311 GetLastMouseButtonPressInfo(aEvent.mButton);
6312 if (aEvent.mMessage == eMouseDown) {
6313 lastButtonPressInfo.mConnectedDownContent =
6314 lastButtonPressInfo.mDownContent =
6315 !aEvent.mClickEventPrevented ? mouseContent : nullptr;
6316 lastButtonPressInfo.mUpContent = nullptr;
6317
6318 if (lastButtonPressInfo.mDownContent) {
6319 if (HTMLInputElement* input = HTMLInputElement::FromNodeOrNull(
6320 lastButtonPressInfo.mDownContent)) {
6321 lastButtonPressInfo.mDownInputControlType = Some(input->ControlType());
6322 } else if (lastButtonPressInfo.mDownContent
6323 ->IsInNativeAnonymousSubtree()) {
6324 if (HTMLInputElement* input = HTMLInputElement::FromNodeOrNull(
6325 lastButtonPressInfo.mDownContent->GetFlattenedTreeParent())) {
6326 lastButtonPressInfo.mDownInputControlType =
6327 Some(input->ControlType());
6328 }
6329 }
6330 }
6331 } else {
6332 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", 6332
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent.mMessage == eMouseUp"
")"); do { MOZ_CrashSequence(__null, 6332); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6333 lastButtonPressInfo.mUpContent = mouseContent;
6334 aEvent.mClickTarget = [&]() -> EventTarget* {
6335 if (aEvent.mClickEventPrevented ||
6336 !lastButtonPressInfo.mConnectedDownContent) {
6337 return nullptr;
6338 }
6339 // If an element was capturing the pointer at dispatching ePointerUp, we
6340 // should dispatch click/auxclick/contextmenu event on it to conform to
6341 // Pointer Events. https://w3c.github.io/pointerevents/#event-dispatch
6342 if (PointerEventHandler::ShouldDispatchClickEventOnCapturingElement(
6343 &aEvent)) {
6344 const RefPtr<Element> capturingElementAtLastPointerUp =
6345 PointerEventHandler::GetPointerCapturingElementAtLastPointerUp();
6346 if (capturingElementAtLastPointerUp &&
6347 capturingElementAtLastPointerUp->GetPresContext(
6348 Element::PresContextFor::eForComposedDoc) == mPresContext) {
6349 return capturingElementAtLastPointerUp;
6350 }
6351 }
6352 return GetCommonAncestorForMouseUp(
6353 mouseContent, lastButtonPressInfo.mConnectedDownContent,
6354 lastButtonPressInfo.mDownInputControlType);
6355 }();
6356 if (aEvent.mClickTarget) {
6357 aEvent.mClickCount = lastButtonPressInfo.mClickCount;
6358 } else {
6359 aEvent.mClickCount = 0;
6360 }
6361 // We'll clear lastButtonPressInfo in PostHandleEvent().
6362 }
6363}
6364
6365// static
6366bool EventStateManager::EventCausesClickEvents(
6367 const WidgetMouseEvent& aMouseEvent) {
6368 if (NS_WARN_IF(aMouseEvent.mMessage != eMouseUp)NS_warn_if_impl(aMouseEvent.mMessage != eMouseUp, "aMouseEvent.mMessage != eMouseUp"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6368
)
) {
6369 return false;
6370 }
6371 // If the mouseup event is synthesized event, we don't need to dispatch
6372 // click events.
6373 if (!aMouseEvent.IsReal()) {
6374 return false;
6375 }
6376 // If mouse is still over same element, clickcount will be > 1.
6377 // If it has moved it will be zero, so no click.
6378 if (!aMouseEvent.mClickCount || !aMouseEvent.mClickTarget) {
6379 return false;
6380 }
6381 // If click event was explicitly prevented, we shouldn't dispatch it.
6382 if (aMouseEvent.mClickEventPrevented) {
6383 return false;
6384 }
6385 // Check that the window isn't disabled before firing a click
6386 // (see bug 366544).
6387 return !(aMouseEvent.mWidget && !aMouseEvent.mWidget->IsEnabled());
6388}
6389
6390nsresult EventStateManager::InitAndDispatchClickEvent(
6391 WidgetMouseEvent* aMouseUpEvent, nsEventStatus* aStatus,
6392 EventMessage aMessage, PresShell* aPresShell, nsIContent* aMouseUpContent,
6393 AutoWeakFrame aCurrentTarget, bool aNoContentDispatch,
6394 nsIContent* aOverrideClickTarget) {
6395 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", 6395
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseUpEvent" ")"
); do { MOZ_CrashSequence(__null, 6395); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6396 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", 6396
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "EventCausesClickEvents(*aMouseUpEvent)"
")"); do { MOZ_CrashSequence(__null, 6396); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6397 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"
, 6397); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseUpContent || aCurrentTarget || aOverrideClickTarget"
")"); do { MOZ_CrashSequence(__null, 6397); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6398
6399 Maybe<WidgetPointerEvent> pointerEvent;
6400 Maybe<WidgetMouseEvent> mouseEvent;
6401 if (IsPointerEventMessage(aMessage)) {
6402 pointerEvent.emplace(aMouseUpEvent->IsTrusted(), aMessage,
6403 aMouseUpEvent->mWidget);
6404 } else {
6405 mouseEvent.emplace(aMouseUpEvent->IsTrusted(), aMessage,
6406 aMouseUpEvent->mWidget, WidgetMouseEvent::eReal);
6407 }
6408
6409 WidgetMouseEvent& mouseOrPointerEvent =
6410 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
6411
6412 mouseOrPointerEvent.mRefPoint = aMouseUpEvent->mRefPoint;
6413 mouseOrPointerEvent.mClickCount = aMouseUpEvent->mClickCount;
6414 mouseOrPointerEvent.mModifiers = aMouseUpEvent->mModifiers;
6415 mouseOrPointerEvent.mButtons = aMouseUpEvent->mButtons;
6416 mouseOrPointerEvent.mTimeStamp = aMouseUpEvent->mTimeStamp;
6417 mouseOrPointerEvent.mFlags.mOnlyChromeDispatch = aNoContentDispatch;
6418 mouseOrPointerEvent.mFlags.mNoContentDispatch = aNoContentDispatch;
6419 mouseOrPointerEvent.mButton = aMouseUpEvent->mButton;
6420 mouseOrPointerEvent.pointerId = aMouseUpEvent->pointerId;
6421 mouseOrPointerEvent.mInputSource = aMouseUpEvent->mInputSource;
6422 nsIContent* target = aMouseUpContent;
6423 nsIFrame* targetFrame = aCurrentTarget;
6424 if (aOverrideClickTarget) {
6425 target = aOverrideClickTarget;
6426 targetFrame = aOverrideClickTarget->GetPrimaryFrame();
6427 }
6428
6429 if (!target->IsInComposedDoc()) {
6430 return NS_OK;
6431 }
6432
6433 // Use local event status for each click event dispatching since it'll be
6434 // cleared by EventStateManager::PreHandleEvent(). Therefore, dispatching
6435 // an event means that previous event status will be ignored.
6436 nsEventStatus status = nsEventStatus_eIgnore;
6437 nsresult rv = aPresShell->HandleEventWithTarget(
6438 &mouseOrPointerEvent, targetFrame, MOZ_KnownLive(target)(target), &status);
6439
6440 // Copy mMultipleActionsPrevented flag from a click event to the mouseup
6441 // event only when it's set to true. It may be set to true if an editor has
6442 // already handled it. This is important to avoid two or more default
6443 // actions handled here.
6444 aMouseUpEvent->mFlags.mMultipleActionsPrevented |=
6445 mouseOrPointerEvent.mFlags.mMultipleActionsPrevented;
6446 // If current status is nsEventStatus_eConsumeNoDefault, we don't need to
6447 // overwrite it.
6448 if (*aStatus == nsEventStatus_eConsumeNoDefault) {
6449 return rv;
6450 }
6451 // If new status is nsEventStatus_eConsumeNoDefault or
6452 // nsEventStatus_eConsumeDoDefault, use it.
6453 if (status == nsEventStatus_eConsumeNoDefault ||
6454 status == nsEventStatus_eConsumeDoDefault) {
6455 *aStatus = status;
6456 return rv;
6457 }
6458 // Otherwise, keep the original status.
6459 return rv;
6460}
6461
6462nsresult EventStateManager::PostHandleMouseUp(
6463 WidgetMouseEvent* aMouseUpEvent, nsEventStatus* aStatus,
6464 nsIContent* aOverrideClickTarget) {
6465 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", 6465
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseUpEvent" ")"
); do { MOZ_CrashSequence(__null, 6465); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6466 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", 6466
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "EventCausesClickEvents(*aMouseUpEvent)"
")"); do { MOZ_CrashSequence(__null, 6466); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6467 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"
, 6467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 6467); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6468
6469 RefPtr<PresShell> presShell = mPresContext->GetPresShell();
6470 if (!presShell) {
6471 return NS_OK;
6472 }
6473
6474 nsCOMPtr<nsIContent> clickTarget =
6475 nsIContent::FromEventTargetOrNull(aMouseUpEvent->mClickTarget);
6476 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"
, 6476); return NS_ERROR_UNEXPECTED; } } while (false)
;
6477
6478 // Fire click events if the event target is still available.
6479 // Note that do not include the eMouseUp event's status since we ignore it
6480 // for compatibility with the other browsers.
6481 nsEventStatus status = nsEventStatus_eIgnore;
6482 nsresult rv = DispatchClickEvents(presShell, aMouseUpEvent, &status,
6483 clickTarget, aOverrideClickTarget);
6484 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"
, 6484)
) {
6485 return rv;
6486 }
6487
6488 // Do not do anything if preceding click events are consumed.
6489 // Note that Chromium dispatches "paste" event and actually pates clipboard
6490 // text into focused editor even if the preceding click events are consumed.
6491 // However, this is different from our traditional behavior and does not
6492 // conform to DOM events. If we need to keep compatibility with Chromium,
6493 // we should change it later.
6494 if (status == nsEventStatus_eConsumeNoDefault) {
6495 *aStatus = nsEventStatus_eConsumeNoDefault;
6496 return NS_OK;
6497 }
6498
6499 // Handle middle click paste if it's enabled and the mouse button is middle.
6500 if (aMouseUpEvent->mButton != MouseButton::eMiddle ||
6501 !WidgetMouseEvent::IsMiddleClickPasteEnabled()) {
6502 return NS_OK;
6503 }
6504 DebugOnly<nsresult> rvIgnored =
6505 HandleMiddleClickPaste(presShell, aMouseUpEvent, &status, nullptr);
6506 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"
, 6507); } } while (false)
6507 "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"
, 6507); } } while (false)
;
6508
6509 // If new status is nsEventStatus_eConsumeNoDefault or
6510 // nsEventStatus_eConsumeDoDefault, use it.
6511 if (*aStatus != nsEventStatus_eConsumeNoDefault &&
6512 (status == nsEventStatus_eConsumeNoDefault ||
6513 status == nsEventStatus_eConsumeDoDefault)) {
6514 *aStatus = status;
6515 }
6516
6517 // Don't return error even if middle mouse paste fails since we haven't
6518 // handled it here.
6519 return NS_OK;
6520}
6521
6522nsresult EventStateManager::DispatchClickEvents(
6523 PresShell* aPresShell, WidgetMouseEvent* aMouseUpEvent,
6524 nsEventStatus* aStatus, nsIContent* aClickTarget,
6525 nsIContent* aOverrideClickTarget) {
6526 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"
, 6526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell"
")"); do { MOZ_CrashSequence(__null, 6526); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6527 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", 6527
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseUpEvent" ")"
); do { MOZ_CrashSequence(__null, 6527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6528 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", 6528
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "EventCausesClickEvents(*aMouseUpEvent)"
")"); do { MOZ_CrashSequence(__null, 6528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6529 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"
, 6529); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 6529); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6530 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"
, 6530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aClickTarget || aOverrideClickTarget"
")"); do { MOZ_CrashSequence(__null, 6530); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6531
6532 bool notDispatchToContents =
6533 (aMouseUpEvent->mButton == MouseButton::eMiddle ||
6534 aMouseUpEvent->mButton == MouseButton::eSecondary);
6535
6536 bool fireAuxClick = notDispatchToContents;
6537
6538 AutoWeakFrame currentTarget = aClickTarget->GetPrimaryFrame();
6539 nsresult rv = InitAndDispatchClickEvent(
6540 aMouseUpEvent, aStatus, ePointerClick, aPresShell, aClickTarget,
6541 currentTarget, notDispatchToContents, aOverrideClickTarget);
6542 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"
, 6542)
) {
6543 return rv;
6544 }
6545
6546 // Fire auxclick event if necessary.
6547 if (fireAuxClick && *aStatus != nsEventStatus_eConsumeNoDefault &&
6548 aClickTarget && aClickTarget->IsInComposedDoc()) {
6549 rv = InitAndDispatchClickEvent(aMouseUpEvent, aStatus, ePointerAuxClick,
6550 aPresShell, aClickTarget, currentTarget,
6551 false, aOverrideClickTarget);
6552 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"
, 6553); } } while (false)
6553 "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"
, 6553); } } while (false)
;
6554 }
6555
6556 // Fire double click event if click count is 2.
6557 if (aMouseUpEvent->mClickCount == 2 && !fireAuxClick && aClickTarget &&
6558 aClickTarget->IsInComposedDoc()) {
6559 rv = InitAndDispatchClickEvent(aMouseUpEvent, aStatus, eMouseDoubleClick,
6560 aPresShell, aClickTarget, currentTarget,
6561 notDispatchToContents, aOverrideClickTarget);
6562 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"
, 6562)
) {
6563 return rv;
6564 }
6565 }
6566
6567 return rv;
6568}
6569
6570nsresult EventStateManager::HandleMiddleClickPaste(
6571 PresShell* aPresShell, WidgetMouseEvent* aMouseOrPointerEvent,
6572 nsEventStatus* aStatus, EditorBase* aEditorBase) {
6573 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"
, 6573); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell"
")"); do { MOZ_CrashSequence(__null, 6573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6574 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", 6574
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrPointerEvent"
")"); do { MOZ_CrashSequence(__null, 6574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6575 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", 6577
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aMouseOrPointerEvent->mMessage == ePointerAuxClick && aMouseOrPointerEvent->mButton == MouseButton::eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)"
")"); do { MOZ_CrashSequence(__null, 6577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6576 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", 6577
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aMouseOrPointerEvent->mMessage == ePointerAuxClick && aMouseOrPointerEvent->mButton == MouseButton::eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)"
")"); do { MOZ_CrashSequence(__null, 6577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6577 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", 6577
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aMouseOrPointerEvent->mMessage == ePointerAuxClick && aMouseOrPointerEvent->mButton == MouseButton::eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)"
")"); do { MOZ_CrashSequence(__null, 6577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6578 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"
, 6578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 6578); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6579 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", 6579
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*aStatus != nsEventStatus_eConsumeNoDefault"
")"); do { MOZ_CrashSequence(__null, 6579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6580
6581 // Even if we're called twice or more for a mouse operation, we should
6582 // handle only once. Although mMultipleActionsPrevented may be set to
6583 // true by different event handler in the future, we can use it for now.
6584 if (aMouseOrPointerEvent->mFlags.mMultipleActionsPrevented) {
6585 return NS_OK;
6586 }
6587 aMouseOrPointerEvent->mFlags.mMultipleActionsPrevented = true;
6588
6589 RefPtr<Selection> selection;
6590 if (aEditorBase) {
6591 selection = aEditorBase->GetSelection();
6592 if (NS_WARN_IF(!selection)NS_warn_if_impl(!selection, "!selection", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6592)
) {
6593 return NS_ERROR_FAILURE;
6594 }
6595 } else {
6596 Document* document = aPresShell->GetDocument();
6597 if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6597)
) {
6598 return NS_ERROR_FAILURE;
6599 }
6600 selection = nsCopySupport::GetSelectionForCopy(document);
6601 if (NS_WARN_IF(!selection)NS_warn_if_impl(!selection, "!selection", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6601)
) {
6602 return NS_ERROR_FAILURE;
6603 }
6604
6605 const nsRange* range = selection->GetRangeAt(0);
6606 if (range) {
6607 nsINode* target = range->GetStartContainer();
6608 if (target && target->OwnerDoc()->IsInChromeDocShell()) {
6609 // In Chrome document, limit middle-click pasting to only the editor
6610 // because it looks odd if pasting works in the focused editor when you
6611 // middle-click toolbar or something which are far from the editor.
6612 // However, as DevTools especially Web Console module assumes that paste
6613 // event will be fired when middle-click even on not editor, don't limit
6614 // it.
6615 return NS_OK;
6616 }
6617 }
6618 }
6619
6620 // Don't modify selection here because we've already set caret to the point
6621 // at "mousedown" event.
6622
6623 nsIClipboard::ClipboardType clipboardType = nsIClipboard::kGlobalClipboard;
6624 nsCOMPtr<nsIClipboard> clipboardService =
6625 do_GetService("@mozilla.org/widget/clipboard;1");
6626 if (clipboardService && clipboardService->IsClipboardTypeSupported(
6627 nsIClipboard::kSelectionClipboard)) {
6628 clipboardType = nsIClipboard::kSelectionClipboard;
6629 }
6630
6631 RefPtr<DataTransfer> dataTransfer;
6632 if (aEditorBase) {
6633 // Create the same DataTransfer object here so we can share it between
6634 // the clipboard event and the call to HandlePaste below. This prevents
6635 // race conditions with Content Analysis on like we see in bug 1918027.
6636 dataTransfer =
6637 aEditorBase->CreateDataTransferForPaste(ePaste, clipboardType);
6638 }
6639 const auto clearDataTransfer = MakeScopeExit([&] {
6640 if (dataTransfer) {
6641 dataTransfer->ClearForPaste();
6642 }
6643 });
6644
6645 // Fire ePaste event by ourselves since we need to dispatch "paste" event
6646 // even if the middle click event was consumed for compatibility with
6647 // Chromium.
6648 if (!nsCopySupport::FireClipboardEvent(ePaste, Some(clipboardType),
6649 aPresShell, selection, dataTransfer)) {
6650 *aStatus = nsEventStatus_eConsumeNoDefault;
6651 return NS_OK;
6652 }
6653
6654 // Although we've fired "paste" event, there is no editor to accept the
6655 // clipboard content.
6656 if (!aEditorBase) {
6657 return NS_OK;
6658 }
6659
6660 // Check if the editor is still the good target to paste.
6661 if (aEditorBase->Destroyed() || aEditorBase->IsReadonly()) {
6662 // XXX Should we consume the event when the editor is readonly and/or
6663 // disabled?
6664 return NS_OK;
6665 }
6666
6667 // The selection may have been modified during reflow. Therefore, we
6668 // should adjust event target to pass IsAcceptableInputEvent().
6669 const nsRange* range = selection->GetRangeAt(0);
6670 if (!range) {
6671 return NS_OK;
6672 }
6673 {
6674 Maybe<WidgetPointerEvent> pointerEvent;
6675 Maybe<WidgetMouseEvent> mouseEvent;
6676 if (aMouseOrPointerEvent->mClass == ePointerEventClass) {
6677 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", 6677
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrPointerEvent->AsPointerEvent()"
")"); do { MOZ_CrashSequence(__null, 6677); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6678 pointerEvent.emplace(
6679 WidgetPointerEvent::MakeCopyFromMouseEvent(*aMouseOrPointerEvent));
6680 } else {
6681 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", 6681
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aMouseOrPointerEvent->AsPointerEvent()"
")"); do { MOZ_CrashSequence(__null, 6681); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6682 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", 6682
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aMouseOrPointerEvent->AsDragEvent()"
")"); do { MOZ_CrashSequence(__null, 6682); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6683 mouseEvent.emplace(*aMouseOrPointerEvent);
6684 }
6685 WidgetMouseEvent& eventCopyRef =
6686 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
6687 eventCopyRef.mOriginalTarget = range->GetStartContainer();
6688 if (NS_WARN_IF(!eventCopyRef.mOriginalTarget)NS_warn_if_impl(!eventCopyRef.mOriginalTarget, "!eventCopyRef.mOriginalTarget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6688
)
||
6689 !aEditorBase->IsAcceptableInputEvent(&eventCopyRef)) {
6690 return NS_OK;
6691 }
6692 }
6693
6694 // If Control key is pressed, we should paste clipboard content as
6695 // quotation. Otherwise, paste it as is.
6696 if (aMouseOrPointerEvent->IsControl()) {
6697 DebugOnly<nsresult> rv = aEditorBase->PasteAsQuotationAsAction(
6698 clipboardType, EditorBase::DispatchPasteEvent::No, dataTransfer);
6699 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"
, 6699); } } while (false)
;
6700 } else {
6701 DebugOnly<nsresult> rv = aEditorBase->PasteAsAction(
6702 clipboardType, EditorBase::DispatchPasteEvent::No, dataTransfer);
6703 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", 6703
); } } while (false)
;
6704 }
6705 *aStatus = nsEventStatus_eConsumeNoDefault;
6706
6707 return NS_OK;
6708}
6709
6710void EventStateManager::ConsumeInteractionData(
6711 Record<nsString, dom::InteractionData>& aInteractions) {
6712 OnTypingInteractionEnded();
6713
6714 aInteractions.Entries().Clear();
6715 auto newEntry = aInteractions.Entries().AppendElement();
6716 newEntry->mKey = u"Typing"_ns;
6717 newEntry->mValue = gTypingInteraction;
6718 gTypingInteraction = {};
6719}
6720
6721nsIFrame* EventStateManager::GetEventTarget() {
6722 PresShell* presShell;
6723 if (mCurrentTarget || !mPresContext ||
6724 !(presShell = mPresContext->GetPresShell())) {
6725 return mCurrentTarget;
6726 }
6727
6728 if (mCurrentTargetContent) {
6729 mCurrentTarget = mPresContext->GetPrimaryFrameFor(mCurrentTargetContent);
6730 if (mCurrentTarget) {
6731 return mCurrentTarget;
6732 }
6733 }
6734
6735 nsIFrame* frame = presShell->GetCurrentEventFrame();
6736 return (mCurrentTarget = frame);
6737}
6738
6739nsIContent* EventStateManager::GetExplicitEventTargetContent(
6740 const WidgetEvent* aEvent /* = nullptr */) {
6741 if (aEvent && (aEvent->mMessage == eFocus || aEvent->mMessage == eBlur)) {
6742 return GetFocusedElement();
6743 }
6744
6745 if (mCurrentTargetContent) {
6746 return mCurrentTargetContent;
6747 }
6748
6749 if (PresShell* presShell = mPresContext->GetPresShell()) {
6750 if (nsIContent* content =
6751 presShell->GetExplicitEventTargetContent(aEvent)) {
6752 return content;
6753 }
6754 }
6755
6756 // Some events here may set mCurrentTarget but not set the corresponding
6757 // event target in the PresShell.
6758 return mCurrentTarget ? mCurrentTarget->GetExplicitEventTargetContent(aEvent)
6759 : nullptr;
6760}
6761
6762nsIContent* EventStateManager::GetEventTargetContent(
6763 const WidgetEvent* aEvent /* = nullptr */) {
6764 return nsContentUtils::GetEventTargetContent(
6765 GetExplicitEventTargetContent(aEvent), aEvent);
6766}
6767
6768static Element* GetLabelTarget(nsIContent* aPossibleLabel) {
6769 mozilla::dom::HTMLLabelElement* label =
6770 mozilla::dom::HTMLLabelElement::FromNode(aPossibleLabel);
6771 if (!label) return nullptr;
6772
6773 return label->GetLabeledElementInternal();
6774}
6775
6776/* static */
6777inline void EventStateManager::DoStateChange(Element* aElement,
6778 ElementState aState,
6779 bool aAddState) {
6780 if (aAddState) {
6781 aElement->AddStates(aState);
6782 } else {
6783 aElement->RemoveStates(aState);
6784 }
6785}
6786
6787/* static */
6788inline void EventStateManager::DoStateChange(nsIContent* aContent,
6789 ElementState aState,
6790 bool aStateAdded) {
6791 if (aContent->IsElement()) {
6792 DoStateChange(aContent->AsElement(), aState, aStateAdded);
6793 }
6794}
6795
6796/* static */
6797void EventStateManager::UpdateAncestorState(nsIContent* aStartNode,
6798 nsIContent* aStopBefore,
6799 ElementState aState,
6800 bool aAddState) {
6801 for (; aStartNode && aStartNode != aStopBefore;
6802 aStartNode = aStartNode->GetFlattenedTreeParent()) {
6803 // We might be starting with a non-element (e.g. a text node) and
6804 // if someone is doing something weird might be ending with a
6805 // non-element too (e.g. a document fragment)
6806 if (!aStartNode->IsElement()) {
6807 continue;
6808 }
6809 Element* element = aStartNode->AsElement();
6810 DoStateChange(element, aState, aAddState);
6811 Element* labelTarget = GetLabelTarget(element);
6812 if (labelTarget) {
6813 DoStateChange(labelTarget, aState, aAddState);
6814 }
6815 }
6816
6817 if (aAddState) {
6818 // We might be in a situation where a node was in hover both
6819 // because it was hovered and because the label for it was
6820 // hovered, and while we stopped hovering the node the label is
6821 // still hovered. Or we might have had two nested labels for the
6822 // same node, and while one is no longer hovered the other still
6823 // is. In that situation, the label that's still hovered will be
6824 // aStopBefore or some ancestor of it, and the call we just made
6825 // to UpdateAncestorState with aAddState = false would have
6826 // removed the hover state from the node. But the node should
6827 // still be in hover state. To handle this situation we need to
6828 // keep walking up the tree and any time we find a label mark its
6829 // corresponding node as still in our state.
6830 for (; aStartNode; aStartNode = aStartNode->GetFlattenedTreeParent()) {
6831 if (!aStartNode->IsElement()) {
6832 continue;
6833 }
6834
6835 Element* labelTarget = GetLabelTarget(aStartNode->AsElement());
6836 if (labelTarget && !labelTarget->State().HasState(aState)) {
6837 DoStateChange(labelTarget, aState, true);
6838 }
6839 }
6840 }
6841}
6842
6843// static
6844bool CanContentHaveActiveState(nsIContent& aContent) {
6845 // Editable content can never become active since their default actions
6846 // are disabled. Watch out for editable content in native anonymous
6847 // subtrees though, as they belong to text controls.
6848 return !aContent.IsEditable() || aContent.IsInNativeAnonymousSubtree();
6849}
6850
6851bool EventStateManager::SetContentState(nsIContent* aContent,
6852 ElementState aState) {
6853 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"
, 6853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ManagesState(aState)"
") (" "Unexpected state" ")"); do { MOZ_CrashSequence(__null
, 6853); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
6854
6855 nsCOMPtr<nsIContent> notifyContent1;
6856 nsCOMPtr<nsIContent> notifyContent2;
6857 bool updateAncestors;
6858
6859 if (aState == ElementState::HOVER || aState == ElementState::ACTIVE) {
6860 // Hover and active are hierarchical
6861 updateAncestors = true;
6862
6863 if (aState == ElementState::ACTIVE) {
6864 if (aContent && !CanContentHaveActiveState(*aContent)) {
6865 aContent = nullptr;
6866 }
6867 if (aContent != mActiveContent) {
6868 notifyContent1 = aContent;
6869 notifyContent2 = mActiveContent;
6870 mActiveContent = aContent;
6871 }
6872 } else {
6873 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"
, 6873); MOZ_PretendNoReturn(); } } while (0)
;
6874 nsIContent* newHover;
6875
6876 if (mPresContext->IsDynamic()) {
6877 newHover = aContent;
6878 } else {
6879 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", 6881
); MOZ_PretendNoReturn(); } } while (0)
6880 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", 6881
); MOZ_PretendNoReturn(); } } while (0)
6881 "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", 6881
); MOZ_PretendNoReturn(); } } while (0)
;
6882 nsIFrame* frame = aContent ? aContent->GetPrimaryFrame() : nullptr;
6883 if (frame && nsLayoutUtils::IsViewportScrollbarFrame(frame)) {
6884 // The scrollbars of viewport should not ignore the hover state.
6885 // Because they are *not* the content of the web page.
6886 newHover = aContent;
6887 } else {
6888 // All contents of the web page should ignore the hover state.
6889 newHover = nullptr;
6890 }
6891 }
6892
6893 if (newHover != mHoverContent) {
6894 notifyContent1 = newHover;
6895 notifyContent2 = mHoverContent;
6896 mHoverContent = newHover;
6897 }
6898 }
6899 } else {
6900 updateAncestors = false;
6901 if (aState == ElementState::DRAGOVER) {
6902 if (aContent != sDragOverContent) {
6903 notifyContent1 = aContent;
6904 notifyContent2 = sDragOverContent;
6905 sDragOverContent = aContent;
6906 }
6907 } else if (aState == ElementState::URLTARGET) {
6908 if (aContent != mURLTargetContent) {
6909 notifyContent1 = aContent;
6910 notifyContent2 = mURLTargetContent;
6911 mURLTargetContent = aContent;
6912 }
6913 }
6914 }
6915
6916 // We need to keep track of which of notifyContent1 and notifyContent2 is
6917 // getting the state set and which is getting it unset. If both are
6918 // non-null, then notifyContent1 is having the state set and notifyContent2
6919 // is having it unset. But if one of them is null, we need to keep track of
6920 // the right thing for notifyContent1 explicitly.
6921 bool content1StateSet = true;
6922 if (!notifyContent1) {
6923 // This is ok because FindCommonAncestor wouldn't find anything
6924 // anyway if notifyContent1 is null.
6925 notifyContent1 = notifyContent2;
6926 notifyContent2 = nullptr;
6927 content1StateSet = false;
6928 }
6929
6930 if (notifyContent1 && mPresContext) {
6931 EnsureDocument(mPresContext);
6932 if (mDocument) {
6933 nsAutoScriptBlocker scriptBlocker;
6934
6935 if (updateAncestors) {
6936 nsCOMPtr<nsIContent> commonAncestor =
6937 FindCommonAncestor(notifyContent1, notifyContent2);
6938 if (notifyContent2) {
6939 // It's very important to first notify the state removal and
6940 // then the state addition, because due to labels it's
6941 // possible that we're removing state from some element but
6942 // then adding it again (say because mHoverContent changed
6943 // from a control to its label).
6944 UpdateAncestorState(notifyContent2, commonAncestor, aState, false);
6945 }
6946 UpdateAncestorState(notifyContent1, commonAncestor, aState,
6947 content1StateSet);
6948 } else {
6949 if (notifyContent2) {
6950 DoStateChange(notifyContent2, aState, false);
6951 }
6952 DoStateChange(notifyContent1, aState, content1StateSet);
6953 }
6954 }
6955 }
6956
6957 return true;
6958}
6959
6960void EventStateManager::RemoveNodeFromChainIfNeeded(ElementState aState,
6961 nsIContent* aContentRemoved,
6962 bool aNotify) {
6963 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", 6963
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState == ElementState::HOVER || aState == ElementState::ACTIVE"
")"); do { MOZ_CrashSequence(__null, 6963); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6964 if (!aContentRemoved->IsElement() ||
6965 !aContentRemoved->AsElement()->State().HasState(aState)) {
6966 return;
6967 }
6968
6969 nsCOMPtr<nsIContent>& leaf =
6970 aState == ElementState::HOVER ? mHoverContent : mActiveContent;
6971
6972 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"
, 6972); AnnotateMozCrashReason("MOZ_ASSERT" "(" "leaf" ")");
do { MOZ_CrashSequence(__null, 6972); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6973 // These two NS_ASSERTIONS below can fail for Shadow DOM sometimes, and it's
6974 // not clear how to best handle it, see
6975 // https://github.com/whatwg/html/issues/4795 and bug 1551621.
6976 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", 6978
); MOZ_PretendNoReturn(); } } while (0)
6977 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", 6978
); MOZ_PretendNoReturn(); } } while (0)
6978 "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", 6978
); MOZ_PretendNoReturn(); } } while (0)
;
6979
6980 nsIContent* newLeaf = aContentRemoved->GetFlattenedTreeParent();
6981 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"
, 6981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newLeaf || newLeaf->IsElement()"
")"); do { MOZ_CrashSequence(__null, 6981); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6982 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", 6983
); MOZ_PretendNoReturn(); } } while (0)
6983 "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", 6983
); MOZ_PretendNoReturn(); } } while (0)
;
6984 if (aNotify) {
6985 SetContentState(newLeaf, aState);
6986 } else {
6987 // We don't update the removed content's state here, since removing NAC
6988 // happens from layout and we don't really want to notify at that point or
6989 // what not.
6990 //
6991 // Also, NAC is not observable and NAC being removed will go away soon.
6992 leaf = newLeaf;
6993 }
6994 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", 6995
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "leaf == newLeaf || (aState == ElementState::ACTIVE && !leaf && !CanContentHaveActiveState(*newLeaf))"
")"); do { MOZ_CrashSequence(__null, 6995); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6995 !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", 6995
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "leaf == newLeaf || (aState == ElementState::ACTIVE && !leaf && !CanContentHaveActiveState(*newLeaf))"
")"); do { MOZ_CrashSequence(__null, 6995); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6996}
6997
6998void EventStateManager::NativeAnonymousContentRemoved(nsIContent* aContent) {
6999 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", 6999
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsRootOfNativeAnonymousSubtree()"
")"); do { MOZ_CrashSequence(__null, 6999); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7000 RemoveNodeFromChainIfNeeded(ElementState::HOVER, aContent, false);
7001 RemoveNodeFromChainIfNeeded(ElementState::ACTIVE, aContent, false);
7002
7003 nsCOMPtr<nsIContent>& lastLeftMouseDownContent =
7004 mLastPrimaryButtonPressInfo.mConnectedDownContent;
7005 if (lastLeftMouseDownContent &&
7006 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
7007 lastLeftMouseDownContent, aContent)) {
7008 lastLeftMouseDownContent = aContent->GetFlattenedTreeParent();
7009 }
7010
7011 nsCOMPtr<nsIContent>& lastMiddleMouseDownContent =
7012 mLastMiddleButtonPressInfo.mConnectedDownContent;
7013 if (lastMiddleMouseDownContent &&
7014 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
7015 lastMiddleMouseDownContent, aContent)) {
7016 lastMiddleMouseDownContent = aContent->GetFlattenedTreeParent();
7017 }
7018
7019 nsCOMPtr<nsIContent>& lastRightMouseDownContent =
7020 mLastSecondaryButtonPressInfo.mConnectedDownContent;
7021 if (lastRightMouseDownContent &&
7022 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
7023 lastRightMouseDownContent, aContent)) {
7024 lastRightMouseDownContent = aContent->GetFlattenedTreeParent();
7025 }
7026}
7027
7028void EventStateManager::ContentInserted(nsIContent* aChild,
7029 const ContentInsertInfo& aInfo) {
7030 if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) {
7031 fm->ContentInserted(aChild, aInfo);
7032 }
7033}
7034void EventStateManager::ContentAppended(nsIContent* aFirstNewContent,
7035 const ContentAppendInfo& aInfo) {
7036 if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) {
7037 fm->ContentAppended(aFirstNewContent, aInfo);
7038 }
7039}
7040
7041void EventStateManager::ContentRemoved(Document* aDocument,
7042 nsIContent* aContent,
7043 const ContentRemoveInfo& aInfo) {
7044 /*
7045 * Anchor and area elements when focused or hovered might make the UI to show
7046 * the current link. We want to make sure that the UI gets informed when they
7047 * are actually removed from the DOM.
7048 */
7049 if (aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area) &&
7050 (aContent->AsElement()->State().HasAtLeastOneOfStates(
7051 ElementState::FOCUS | ElementState::HOVER))) {
7052 Element* element = aContent->AsElement();
7053 element->LeaveLink(element->GetPresContext(Element::eForComposedDoc));
7054 }
7055
7056 if (aContent->IsElement()) {
7057 if (RefPtr<nsPresContext> presContext = mPresContext) {
7058 IMEStateManager::OnRemoveContent(*presContext,
7059 MOZ_KnownLive(*aContent->AsElement())(*aContent->AsElement()));
7060 }
7061 WheelTransaction::OnRemoveElement(aContent);
7062 }
7063
7064 // inform the focus manager that the content is being removed. If this
7065 // content is focused, the focus will be removed without firing events.
7066 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
7067 fm->ContentRemoved(aDocument, aContent, aInfo);
7068 }
7069
7070 RemoveNodeFromChainIfNeeded(ElementState::HOVER, aContent, true);
7071 RemoveNodeFromChainIfNeeded(ElementState::ACTIVE, aContent, true);
7072
7073 if (sDragOverContent &&
7074 sDragOverContent->OwnerDoc() == aContent->OwnerDoc() &&
7075 nsContentUtils::ContentIsFlattenedTreeDescendantOf(sDragOverContent,
7076 aContent)) {
7077 sDragOverContent = nullptr;
7078 }
7079
7080 if (!aInfo.mNewParent) {
7081 PointerEventHandler::ReleaseIfCaptureByDescendant(aContent);
7082 }
7083
7084 if (mMouseEnterLeaveHelper) {
7085 const bool hadMouseOutTarget =
7086 mMouseEnterLeaveHelper->GetOutEventTarget() != nullptr;
7087 mMouseEnterLeaveHelper->ContentRemoved(*aContent);
7088 if (hadMouseOutTarget && !mMouseEnterLeaveHelper->GetOutEventTarget()) {
7089 if (PresShell* const presShell =
7090 mPresContext ? mPresContext->GetPresShell() : nullptr) {
7091 // If we lose the mouseout target, we need to dispatch mouseover on an
7092 // ancestor. For ensuring the chance to do it before next user input,
7093 // we need a synthetic mouse move.
7094 const bool requiresToSynthesizeMouseMove = [&]() {
7095 // If the last mouse event is caused by a pointing device which does
7096 // not support hover state and it's inactive, we don't need to
7097 // synthesize mouse move.
7098 const PointerInfo* const lastMouseInfo =
7099 PointerEventHandler::GetLastMouseInfo();
7100 return lastMouseInfo && (lastMouseInfo->InputSourceSupportsHover() ||
7101 lastMouseInfo->mIsActive);
7102 }();
7103 if (requiresToSynthesizeMouseMove) {
7104 presShell->SynthesizeMouseMove(false);
7105 }
7106 }
7107 }
7108 }
7109 for (const auto& entry : mPointersEnterLeaveHelper) {
7110 if (entry.GetData()) {
7111 entry.GetData()->ContentRemoved(*aContent);
7112 }
7113 }
7114
7115 NotifyContentWillBeRemovedForGesture(*aContent);
7116}
7117
7118bool EventStateManager::EventStatusOK(WidgetGUIEvent* aEvent) {
7119 return !(aEvent->mMessage == eMouseDown &&
7120 aEvent->AsMouseEvent()->mButton == MouseButton::ePrimary &&
7121 !sNormalLMouseEventInProcess);
7122}
7123
7124//-------------------------------------------
7125// Access Key Registration
7126//-------------------------------------------
7127void EventStateManager::RegisterAccessKey(Element* aElement, uint32_t aKey) {
7128 if (aElement && !mAccessKeys.Contains(aElement)) {
7129 mAccessKeys.AppendObject(aElement);
7130 }
7131}
7132
7133void EventStateManager::UnregisterAccessKey(Element* aElement, uint32_t aKey) {
7134 if (aElement) {
7135 mAccessKeys.RemoveObject(aElement);
7136 }
7137}
7138
7139uint32_t EventStateManager::GetRegisteredAccessKey(Element* aElement) {
7140 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"
, 7140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 7140); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7141
7142 if (!mAccessKeys.Contains(aElement)) {
7143 return 0;
7144 }
7145
7146 nsAutoString accessKey;
7147 aElement->GetAttr(nsGkAtoms::accesskey, accessKey);
7148 return accessKey.First();
7149}
7150
7151PresShell* EventStateManager::GetRootPresShell() const {
7152 PresShell* const presShell = GetPresShell();
7153 return presShell ? presShell->GetRootPresShell() : nullptr;
7154}
7155
7156void EventStateManager::EnsureDocument(nsPresContext* aPresContext) {
7157 if (!mDocument) mDocument = aPresContext->Document();
7158}
7159
7160void EventStateManager::FlushLayout(nsPresContext* aPresContext) {
7161 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"
, 7161); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
") (" "nullptr ptr" ")"); do { MOZ_CrashSequence(__null, 7161
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7162 if (RefPtr<PresShell> presShell = aPresContext->GetPresShell()) {
7163 presShell->FlushPendingNotifications(FlushType::InterruptibleLayout);
7164 }
7165}
7166
7167Element* EventStateManager::GetFocusedElement() {
7168 nsFocusManager* fm = nsFocusManager::GetFocusManager();
7169 EnsureDocument(mPresContext);
7170 if (!fm || !mDocument) {
7171 return nullptr;
7172 }
7173
7174 nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
7175 return nsFocusManager::GetFocusedDescendant(
7176 mDocument->GetWindow(), nsFocusManager::eOnlyCurrentWindow,
7177 getter_AddRefs(focusedWindow));
7178}
7179
7180//-------------------------------------------------------
7181// Return true if the docshell is visible
7182
7183bool EventStateManager::IsShellVisible(nsIDocShell* aShell) {
7184 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"
, 7184); MOZ_PretendNoReturn(); } } while (0)
;
7185
7186 nsCOMPtr<nsIBaseWindow> basewin = do_QueryInterface(aShell);
7187 if (!basewin) return true;
7188
7189 bool isVisible = true;
7190 basewin->GetVisibility(&isVisible);
7191
7192 // We should be doing some additional checks here so that
7193 // we don't tab into hidden tabs of tabbrowser. -bryner
7194
7195 return isVisible;
7196}
7197
7198nsresult EventStateManager::DoContentCommandEvent(
7199 WidgetContentCommandEvent* aEvent) {
7200 EnsureDocument(mPresContext);
7201 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", 7201
); return NS_ERROR_FAILURE; } } while (false)
;
7202 nsCOMPtr<nsPIDOMWindowOuter> window(mDocument->GetWindow());
7203 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", 7203
); return NS_ERROR_FAILURE; } } while (false)
;
7204
7205 nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
7206 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", 7206
); return NS_ERROR_FAILURE; } } while (false)
;
7207 const char* cmd;
7208 bool maybeNeedToHandleInRemote = false;
7209 switch (aEvent->mMessage) {
7210 case eContentCommandCut:
7211 cmd = "cmd_cut";
7212 maybeNeedToHandleInRemote = true;
7213 break;
7214 case eContentCommandCopy:
7215 cmd = "cmd_copy";
7216 maybeNeedToHandleInRemote = true;
7217 break;
7218 case eContentCommandPaste:
7219 cmd = "cmd_paste";
7220 maybeNeedToHandleInRemote = true;
7221 break;
7222 case eContentCommandDelete:
7223 cmd = "cmd_delete";
7224 maybeNeedToHandleInRemote = true;
7225 break;
7226 case eContentCommandUndo:
7227 cmd = "cmd_undo";
7228 maybeNeedToHandleInRemote = true;
7229 break;
7230 case eContentCommandRedo:
7231 cmd = "cmd_redo";
7232 maybeNeedToHandleInRemote = true;
7233 break;
7234 case eContentCommandPasteTransferable:
7235 cmd = "cmd_pasteTransferable";
7236 break;
7237 case eContentCommandLookUpDictionary:
7238 cmd = "cmd_lookUpDictionary";
7239 break;
7240 default:
7241 return NS_ERROR_NOT_IMPLEMENTED;
7242 }
7243 if (XRE_IsParentProcess() && maybeNeedToHandleInRemote) {
7244 if (BrowserParent* remote = BrowserParent::GetFocused()) {
7245 if (!aEvent->mOnlyEnabledCheck) {
7246 remote->SendSimpleContentCommandEvent(*aEvent);
7247 }
7248 // XXX The command may be disabled in the parent process. Perhaps, we
7249 // should set actual enabled state in the parent process here and there
7250 // should be another bool flag which indicates whether the content is sent
7251 // to a remote process.
7252 aEvent->mIsEnabled = true;
7253 aEvent->mSucceeded = true;
7254 return NS_OK;
7255 }
7256 }
7257 // If user tries to do something, user must try to do it in visible window.
7258 // So, let's retrieve controller of visible window.
7259 nsCOMPtr<nsIController> controller;
7260 nsresult rv =
7261 root->GetControllerForCommand(cmd, true, getter_AddRefs(controller));
7262 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"
, 7262); return rv; } } while (false)
;
7263 if (!controller) {
7264 // When GetControllerForCommand succeeded but there is no controller, the
7265 // command isn't supported.
7266 aEvent->mIsEnabled = false;
7267 } else {
7268 bool canDoIt;
7269 rv = controller->IsCommandEnabled(cmd, &canDoIt);
7270 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"
, 7270); return rv; } } while (false)
;
7271 aEvent->mIsEnabled = canDoIt;
7272 if (canDoIt && !aEvent->mOnlyEnabledCheck) {
7273 switch (aEvent->mMessage) {
7274 case eContentCommandPasteTransferable: {
7275 BrowserParent* remote = BrowserParent::GetFocused();
7276 if (remote) {
7277 IPCTransferable ipcTransferable;
7278 nsContentUtils::TransferableToIPCTransferable(
7279 aEvent->mTransferable, &ipcTransferable, false,
7280 remote->Manager());
7281 remote->SendPasteTransferable(std::move(ipcTransferable));
7282 rv = NS_OK;
7283 } else {
7284 nsCOMPtr<nsICommandController> commandController =
7285 do_QueryInterface(controller);
7286 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"
, 7286); return NS_ERROR_UNEXPECTED; } } while (false)
;
7287
7288 RefPtr<nsCommandParams> params = new nsCommandParams();
7289 rv = params->SetISupports("transferable", aEvent->mTransferable);
7290 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"
, 7290)
) {
7291 return rv;
7292 }
7293 rv = commandController->DoCommandWithParams(cmd, params);
7294 }
7295 break;
7296 }
7297
7298 case eContentCommandLookUpDictionary: {
7299 nsCOMPtr<nsICommandController> commandController =
7300 do_QueryInterface(controller);
7301 if (NS_WARN_IF(!commandController)NS_warn_if_impl(!commandController, "!commandController", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7301)
) {
7302 return NS_ERROR_FAILURE;
7303 }
7304
7305 RefPtr<nsCommandParams> params = new nsCommandParams();
7306 rv = params->SetInt("x", aEvent->mRefPoint.x);
7307 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"
, 7307)
) {
7308 return rv;
7309 }
7310
7311 rv = params->SetInt("y", aEvent->mRefPoint.y);
7312 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"
, 7312)
) {
7313 return rv;
7314 }
7315
7316 rv = commandController->DoCommandWithParams(cmd, params);
7317 break;
7318 }
7319
7320 default:
7321 rv = controller->DoCommand(cmd);
7322 break;
7323 }
7324 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"
, 7324); return rv; } } while (false)
;
7325 }
7326 }
7327 aEvent->mSucceeded = true;
7328 return NS_OK;
7329}
7330
7331nsresult EventStateManager::DoContentCommandInsertTextEvent(
7332 WidgetContentCommandEvent* aEvent) {
7333 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"
, 7333); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 7333); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7334 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", 7334
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eContentCommandInsertText"
")"); do { MOZ_CrashSequence(__null, 7334); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7335 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", 7335
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aEvent->mString.isSome()"
")"); do { MOZ_CrashSequence(__null, 7335); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7336 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"
, 7336); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aEvent->mString.ref().IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 7336); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7337
7338 aEvent->mIsEnabled = false;
7339 aEvent->mSucceeded = false;
7340
7341 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"
, 7341); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7342
7343 if (XRE_IsParentProcess()) {
7344 // Handle it in focused content process if there is.
7345 if (BrowserParent* remote = BrowserParent::GetFocused()) {
7346 if (!aEvent->mOnlyEnabledCheck) {
7347 remote->SendInsertText(*aEvent);
7348 }
7349 // XXX The remote process may be not editable right now. Therefore, this
7350 // may be different from actual state in the remote process.
7351 aEvent->mIsEnabled = true;
7352 aEvent->mSucceeded = true;
7353 return NS_OK;
7354 }
7355 }
7356
7357 // If there is no active editor in this process, we should treat the command
7358 // is disabled.
7359 RefPtr<EditorBase> activeEditor =
7360 nsContentUtils::GetActiveEditor(mPresContext);
7361 if (!activeEditor) {
7362 aEvent->mSucceeded = true;
7363 return NS_OK;
7364 }
7365
7366 nsresult rv = activeEditor->InsertTextAsAction(aEvent->mString.ref());
7367 aEvent->mIsEnabled = rv != NS_SUCCESS_DOM_NO_OPERATION;
7368 aEvent->mSucceeded = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
7369 return NS_OK;
7370}
7371
7372nsresult EventStateManager::DoContentCommandReplaceTextEvent(
7373 WidgetContentCommandEvent* aEvent) {
7374 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"
, 7374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 7374); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7375 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", 7375
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eContentCommandReplaceText"
")"); do { MOZ_CrashSequence(__null, 7375); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7376 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", 7376
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aEvent->mString.isSome()"
")"); do { MOZ_CrashSequence(__null, 7376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7377 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"
, 7377); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aEvent->mString.ref().IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 7377); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7378
7379 aEvent->mIsEnabled = false;
7380 aEvent->mSucceeded = false;
7381
7382 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"
, 7382); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7383
7384 if (XRE_IsParentProcess()) {
7385 // Handle it in focused content process if there is.
7386 if (BrowserParent* remote = BrowserParent::GetFocused()) {
7387 if (!aEvent->mOnlyEnabledCheck) {
7388 (void)remote->SendReplaceText(*aEvent);
7389 }
7390 // XXX The remote process may be not editable right now. Therefore, this
7391 // may be different from actual state in the remote process.
7392 aEvent->mIsEnabled = true;
7393 aEvent->mSucceeded = true;
7394 return NS_OK;
7395 }
7396 }
7397
7398 // If there is no active editor in this process, we should treat the command
7399 // is disabled.
7400 RefPtr<EditorBase> activeEditor =
7401 nsContentUtils::GetActiveEditor(mPresContext);
7402 if (NS_WARN_IF(!activeEditor)NS_warn_if_impl(!activeEditor, "!activeEditor", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7402)
) {
7403 aEvent->mSucceeded = true;
7404 return NS_OK;
7405 }
7406
7407 RefPtr<TextComposition> composition =
7408 IMEStateManager::GetTextCompositionFor(mPresContext);
7409 if (NS_WARN_IF(composition)NS_warn_if_impl(composition, "composition", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7409)
) {
7410 // We don't support replace text action during composition.
7411 aEvent->mSucceeded = true;
7412 return NS_OK;
7413 }
7414
7415 // Don't try to compute range in DOM from text offsets for EditContext,
7416 // since it will often be incorrect.
7417 if (RefPtr editContext = activeEditor->ComputeEditContext()) {
7418 editContext->DoContentCommandReplaceText(*aEvent);
7419 return NS_OK;
7420 }
7421
7422 ContentEventHandler handler(mPresContext);
7423 RefPtr<nsRange> range = handler.GetRangeFromFlatTextOffset(
7424 aEvent, aEvent->mSelection.mOffset,
7425 aEvent->mSelection.mReplaceSrcString.Length());
7426 if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7426)
) {
7427 aEvent->mSucceeded = false;
7428 return NS_OK;
7429 }
7430
7431 // If original replacement text isn't matched with selection text, throws
7432 // error.
7433 nsAutoString targetStr;
7434 nsresult rv = handler.GenerateFlatTextContent(range, targetStr);
7435 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"
, 7435)
) {
7436 aEvent->mSucceeded = false;
7437 return NS_OK;
7438 }
7439 if (!aEvent->mSelection.mReplaceSrcString.Equals(targetStr)) {
7440 aEvent->mSucceeded = false;
7441 return NS_OK;
7442 }
7443
7444 rv = activeEditor->ReplaceTextAsAction(
7445 aEvent->mString.ref(), range,
7446 TextEditor::AllowBeforeInputEventCancelable::Yes,
7447 aEvent->mSelection.mPreventSetSelection
7448 ? EditorBase::PreventSetSelection::Yes
7449 : EditorBase::PreventSetSelection::No);
7450 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"
, 7450)
) {
7451 aEvent->mSucceeded = false;
7452 return NS_OK;
7453 }
7454
7455 aEvent->mIsEnabled = rv != NS_SUCCESS_DOM_NO_OPERATION;
7456 aEvent->mSucceeded = true;
7457 return NS_OK;
7458}
7459
7460nsresult EventStateManager::DoContentCommandScrollEvent(
7461 WidgetContentCommandEvent* aEvent) {
7462 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"
, 7462); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7463 PresShell* presShell = mPresContext->GetPresShell();
7464 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", 7464
); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7465 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"
, 7465); return NS_ERROR_INVALID_ARG; } } while (false)
;
7466
7467 ScrollUnit scrollUnit;
7468 switch (aEvent->mScroll.mUnit) {
7469 case WidgetContentCommandEvent::eCmdScrollUnit_Line:
7470 scrollUnit = ScrollUnit::LINES;
7471 break;
7472 case WidgetContentCommandEvent::eCmdScrollUnit_Page:
7473 scrollUnit = ScrollUnit::PAGES;
7474 break;
7475 case WidgetContentCommandEvent::eCmdScrollUnit_Whole:
7476 scrollUnit = ScrollUnit::WHOLE;
7477 break;
7478 default:
7479 return NS_ERROR_INVALID_ARG;
7480 }
7481
7482 aEvent->mSucceeded = true;
7483
7484 ScrollContainerFrame* sf =
7485 presShell->GetScrollContainerFrameToScroll(layers::EitherScrollDirection);
7486 aEvent->mIsEnabled =
7487 sf ? (aEvent->mScroll.mIsHorizontal ? WheelHandlingUtils::CanScrollOn(
7488 sf, aEvent->mScroll.mAmount, 0)
7489 : WheelHandlingUtils::CanScrollOn(
7490 sf, 0, aEvent->mScroll.mAmount))
7491 : false;
7492
7493 if (!aEvent->mIsEnabled || aEvent->mOnlyEnabledCheck) {
7494 return NS_OK;
7495 }
7496
7497 nsIntPoint pt(0, 0);
7498 if (aEvent->mScroll.mIsHorizontal) {
7499 pt.x = aEvent->mScroll.mAmount;
7500 } else {
7501 pt.y = aEvent->mScroll.mAmount;
7502 }
7503
7504 // The caller may want synchronous scrolling.
7505 sf->ScrollBy(pt, scrollUnit, ScrollMode::Instant);
7506 return NS_OK;
7507}
7508
7509void EventStateManager::SetActiveManager(EventStateManager* aNewESM,
7510 nsIContent* aContent) {
7511 if (sActiveESM && aNewESM != sActiveESM) {
7512 sActiveESM->SetContentState(nullptr, ElementState::ACTIVE);
7513 }
7514 sActiveESM = aNewESM;
7515 if (sActiveESM && aContent) {
7516 sActiveESM->SetContentState(aContent, ElementState::ACTIVE);
7517 }
7518}
7519
7520void EventStateManager::ClearGlobalActiveContent(EventStateManager* aClearer) {
7521 if (aClearer) {
7522 aClearer->SetContentState(nullptr, ElementState::ACTIVE);
7523 if (sDragOverContent) {
7524 aClearer->SetContentState(nullptr, ElementState::DRAGOVER);
7525 }
7526 }
7527 if (sActiveESM && aClearer != sActiveESM) {
7528 sActiveESM->SetContentState(nullptr, ElementState::ACTIVE);
7529 }
7530 sActiveESM = nullptr;
7531}
7532
7533/******************************************************************/
7534/* mozilla::EventStateManager::DeltaAccumulator */
7535/******************************************************************/
7536
7537void EventStateManager::DeltaAccumulator::InitLineOrPageDelta(
7538 nsIFrame* aTargetFrame, EventStateManager* aESM, WidgetWheelEvent* aEvent) {
7539 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"
, 7539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aESM" ")");
do { MOZ_CrashSequence(__null, 7539); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7540 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"
, 7540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 7540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7541
7542 // Reset if the previous wheel event is too old.
7543 if (!mLastTime.IsNull()) {
7544 TimeDuration duration = TimeStamp::Now() - mLastTime;
7545 if (duration.ToMilliseconds() >
7546 StaticPrefs::mousewheel_transaction_timeout()) {
7547 Reset();
7548 }
7549 }
7550 // If we have accumulated delta, we may need to reset it.
7551 if (IsInTransaction()) {
7552 // If wheel event type is changed, reset the values.
7553 if (mHandlingDeltaMode != aEvent->mDeltaMode ||
7554 mIsNoLineOrPageDeltaDevice != aEvent->mIsNoLineOrPageDelta) {
7555 Reset();
7556 } else {
7557 // If the delta direction is changed, we should reset only the
7558 // accumulated values.
7559 if (mX && aEvent->mDeltaX && ((aEvent->mDeltaX > 0.0) != (mX > 0.0))) {
7560 mX = mPendingScrollAmountX = 0.0;
7561 }
7562 if (mY && aEvent->mDeltaY && ((aEvent->mDeltaY > 0.0) != (mY > 0.0))) {
7563 mY = mPendingScrollAmountY = 0.0;
7564 }
7565 }
7566 }
7567
7568 mHandlingDeltaMode = aEvent->mDeltaMode;
7569 mIsNoLineOrPageDeltaDevice = aEvent->mIsNoLineOrPageDelta;
7570
7571 {
7572 ScrollContainerFrame* scrollTarget = aESM->ComputeScrollTarget(
7573 aTargetFrame, aEvent, COMPUTE_DEFAULT_ACTION_TARGET);
7574 nsPresContext* pc = scrollTarget ? scrollTarget->PresContext()
7575 : aTargetFrame->PresContext();
7576 aEvent->mScrollAmount = aESM->GetScrollAmount(pc, aEvent, scrollTarget);
7577 }
7578
7579 // If it's handling neither a device that does not provide line or page deltas
7580 // nor delta values multiplied by prefs, we must not modify lineOrPageDelta
7581 // values.
7582 // TODO(emilio): Does this care about overridden scroll speed?
7583 if (!mIsNoLineOrPageDeltaDevice &&
7584 !EventStateManager::WheelPrefs::GetInstance()
7585 ->NeedToComputeLineOrPageDelta(aEvent)) {
7586 // Set the delta values to mX and mY. They would be used when above block
7587 // resets mX/mY/mPendingScrollAmountX/mPendingScrollAmountY if the direction
7588 // is changed.
7589 // NOTE: We shouldn't accumulate the delta values, it might could cause
7590 // overflow even though it's not a realistic situation.
7591 if (aEvent->mDeltaX) {
7592 mX = aEvent->mDeltaX;
7593 }
7594 if (aEvent->mDeltaY) {
7595 mY = aEvent->mDeltaY;
7596 }
7597 mLastTime = TimeStamp::Now();
7598 return;
7599 }
7600
7601 mX += aEvent->mDeltaX;
7602 mY += aEvent->mDeltaY;
7603
7604 if (mHandlingDeltaMode == WheelEvent_Binding::DOM_DELTA_PIXEL) {
7605 // Records pixel delta values and init mLineOrPageDeltaX and
7606 // mLineOrPageDeltaY for wheel events which are caused by pixel only
7607 // devices. Ignore mouse wheel transaction for computing this. The
7608 // lineOrPageDelta values will be used by dispatching legacy
7609 // eMouseScrollEventClass (DOMMouseScroll) but not be used for scrolling
7610 // of default action. The transaction should be used only for the default
7611 // action.
7612 auto scrollAmountInCSSPixels =
7613 CSSIntSize::FromAppUnitsRounded(aEvent->mScrollAmount);
7614
7615 aEvent->mLineOrPageDeltaX = RoundDown(mX) / scrollAmountInCSSPixels.width;
7616 aEvent->mLineOrPageDeltaY = RoundDown(mY) / scrollAmountInCSSPixels.height;
7617
7618 mX -= aEvent->mLineOrPageDeltaX * scrollAmountInCSSPixels.width;
7619 mY -= aEvent->mLineOrPageDeltaY * scrollAmountInCSSPixels.height;
7620 } else {
7621 aEvent->mLineOrPageDeltaX = RoundDown(mX);
7622 aEvent->mLineOrPageDeltaY = RoundDown(mY);
7623 mX -= aEvent->mLineOrPageDeltaX;
7624 mY -= aEvent->mLineOrPageDeltaY;
7625 }
7626
7627 mLastTime = TimeStamp::Now();
7628}
7629
7630void EventStateManager::DeltaAccumulator::Reset() {
7631 mX = mY = 0.0;
7632 mPendingScrollAmountX = mPendingScrollAmountY = 0.0;
7633 mHandlingDeltaMode = UINT32_MAX(4294967295U);
7634 mIsNoLineOrPageDeltaDevice = false;
7635}
7636
7637nsIntPoint
7638EventStateManager::DeltaAccumulator::ComputeScrollAmountForDefaultAction(
7639 WidgetWheelEvent* aEvent, const nsIntSize& aScrollAmountInDevPixels) {
7640 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"
, 7640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 7640); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7641
7642 DeltaValues acceleratedDelta = WheelTransaction::AccelerateWheelDelta(aEvent);
7643
7644 nsIntPoint result(0, 0);
7645 if (aEvent->mDeltaMode == WheelEvent_Binding::DOM_DELTA_PIXEL) {
7646 mPendingScrollAmountX += acceleratedDelta.deltaX;
7647 mPendingScrollAmountY += acceleratedDelta.deltaY;
7648 } else {
7649 mPendingScrollAmountX +=
7650 aScrollAmountInDevPixels.width * acceleratedDelta.deltaX;
7651 mPendingScrollAmountY +=
7652 aScrollAmountInDevPixels.height * acceleratedDelta.deltaY;
7653 }
7654 result.x = RoundDown(mPendingScrollAmountX);
7655 result.y = RoundDown(mPendingScrollAmountY);
7656 mPendingScrollAmountX -= result.x;
7657 mPendingScrollAmountY -= result.y;
7658
7659 return result;
7660}
7661
7662/******************************************************************/
7663/* mozilla::EventStateManager::WheelPrefs */
7664/******************************************************************/
7665
7666// static
7667EventStateManager::WheelPrefs* EventStateManager::WheelPrefs::GetInstance() {
7668 if (!sInstance) {
7669 sInstance = new WheelPrefs();
7670 }
7671 return sInstance;
7672}
7673
7674// static
7675void EventStateManager::WheelPrefs::Shutdown() {
7676 delete sInstance;
7677 sInstance = nullptr;
7678}
7679
7680// static
7681void EventStateManager::WheelPrefs::OnPrefChanged(const char* aPrefName,
7682 void* aClosure) {
7683 // forget all prefs, it's not problem for performance.
7684 sInstance->Reset();
7685 DeltaAccumulator::GetInstance()->Reset();
7686}
7687
7688EventStateManager::WheelPrefs::WheelPrefs() {
7689 Reset();
7690 Preferences::RegisterPrefixCallback(OnPrefChanged, "mousewheel.");
7691}
7692
7693EventStateManager::WheelPrefs::~WheelPrefs() {
7694 Preferences::UnregisterPrefixCallback(OnPrefChanged, "mousewheel.");
7695}
7696
7697void EventStateManager::WheelPrefs::Reset() { memset(mInit, 0, sizeof(mInit)); }
7698
7699EventStateManager::WheelPrefs::Index EventStateManager::WheelPrefs::GetIndexFor(
7700 const WidgetWheelEvent* aEvent) {
7701 if (!aEvent) {
7702 return INDEX_DEFAULT;
7703 }
7704
7705 Modifiers modifiers = (aEvent->mModifiers & (MODIFIER_ALT | MODIFIER_CONTROL |
7706 MODIFIER_META | MODIFIER_SHIFT));
7707
7708 switch (modifiers) {
7709 case MODIFIER_ALT:
7710 return INDEX_ALT;
7711 case MODIFIER_CONTROL:
7712 return INDEX_CONTROL;
7713 case MODIFIER_META:
7714 return INDEX_META;
7715 case MODIFIER_SHIFT:
7716 return INDEX_SHIFT;
7717 default:
7718 // If two or more modifier keys are pressed, we should use default
7719 // settings.
7720 return INDEX_DEFAULT;
7721 }
7722}
7723
7724void EventStateManager::WheelPrefs::GetBasePrefName(
7725 EventStateManager::WheelPrefs::Index aIndex, nsACString& aBasePrefName) {
7726 aBasePrefName.AssignLiteral("mousewheel.");
7727 switch (aIndex) {
7728 case INDEX_ALT:
7729 aBasePrefName.AppendLiteral("with_alt.");
7730 break;
7731 case INDEX_CONTROL:
7732 aBasePrefName.AppendLiteral("with_control.");
7733 break;
7734 case INDEX_META:
7735 aBasePrefName.AppendLiteral("with_meta.");
7736 break;
7737 case INDEX_SHIFT:
7738 aBasePrefName.AppendLiteral("with_shift.");
7739 break;
7740 case INDEX_DEFAULT:
7741 default:
7742 aBasePrefName.AppendLiteral("default.");
7743 break;
7744 }
7745}
7746
7747void EventStateManager::WheelPrefs::Init(
7748 EventStateManager::WheelPrefs::Index aIndex) {
7749 if (mInit[aIndex]) {
7750 return;
7751 }
7752 mInit[aIndex] = true;
7753
7754 nsAutoCString basePrefName;
7755 GetBasePrefName(aIndex, basePrefName);
7756
7757 nsAutoCString prefNameX(basePrefName);
7758 prefNameX.AppendLiteral("delta_multiplier_x");
7759 mMultiplierX[aIndex] =
7760 static_cast<double>(Preferences::GetInt(prefNameX.get(), 100)) / 100;
7761
7762 nsAutoCString prefNameY(basePrefName);
7763 prefNameY.AppendLiteral("delta_multiplier_y");
7764 mMultiplierY[aIndex] =
7765 static_cast<double>(Preferences::GetInt(prefNameY.get(), 100)) / 100;
7766
7767 nsAutoCString prefNameZ(basePrefName);
7768 prefNameZ.AppendLiteral("delta_multiplier_z");
7769 mMultiplierZ[aIndex] =
7770 static_cast<double>(Preferences::GetInt(prefNameZ.get(), 100)) / 100;
7771
7772 nsAutoCString prefNameAction(basePrefName);
7773 prefNameAction.AppendLiteral("action");
7774 int32_t action = Preferences::GetInt(prefNameAction.get(), ACTION_SCROLL);
7775 if (action < int32_t(ACTION_NONE) || action > int32_t(ACTION_LAST)) {
7776 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"
, 7776)
;
7777 action = ACTION_SCROLL;
7778 }
7779 mActions[aIndex] = static_cast<Action>(action);
7780
7781 // Compute action values overridden by .override_x pref.
7782 // At present, override is possible only for the x-direction
7783 // because this pref is introduced mainly for tilt wheels.
7784 // Note that ACTION_HORIZONTALIZED_SCROLL isn't a valid value for this pref
7785 // because it affects only to deltaY.
7786 prefNameAction.AppendLiteral(".override_x");
7787 int32_t actionOverrideX = Preferences::GetInt(prefNameAction.get(), -1);
7788 if (actionOverrideX < -1 || actionOverrideX > int32_t(ACTION_LAST) ||
7789 actionOverrideX == ACTION_HORIZONTALIZED_SCROLL) {
7790 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"
, 7790)
;
7791 actionOverrideX = -1;
7792 }
7793 mOverriddenActionsX[aIndex] = (actionOverrideX == -1)
7794 ? static_cast<Action>(action)
7795 : static_cast<Action>(actionOverrideX);
7796}
7797
7798void EventStateManager::WheelPrefs::GetMultiplierForDeltaXAndY(
7799 const WidgetWheelEvent* aEvent, Index aIndex, double* aMultiplierForDeltaX,
7800 double* aMultiplierForDeltaY) {
7801 *aMultiplierForDeltaX = mMultiplierX[aIndex];
7802 *aMultiplierForDeltaY = mMultiplierY[aIndex];
7803 // If the event has been horizontalized(I.e. treated as a horizontal wheel
7804 // scroll for a vertical wheel scroll), then we should swap mMultiplierX and
7805 // mMultiplierY. By doing this, multipliers will still apply to the delta
7806 // values they origianlly corresponded to.
7807 if (aEvent->mDeltaValuesHorizontalizedForDefaultHandler &&
7808 ComputeActionFor(aEvent) == ACTION_HORIZONTALIZED_SCROLL) {
7809 std::swap(*aMultiplierForDeltaX, *aMultiplierForDeltaY);
7810 }
7811}
7812
7813void EventStateManager::WheelPrefs::ApplyUserPrefsToDelta(
7814 WidgetWheelEvent* aEvent) {
7815 if (aEvent->mCustomizedByUserPrefs) {
7816 return;
7817 }
7818
7819 Index index = GetIndexFor(aEvent);
7820 Init(index);
7821
7822 double multiplierForDeltaX = 1.0, multiplierForDeltaY = 1.0;
7823 GetMultiplierForDeltaXAndY(aEvent, index, &multiplierForDeltaX,
7824 &multiplierForDeltaY);
7825 aEvent->mDeltaX *= multiplierForDeltaX;
7826 aEvent->mDeltaY *= multiplierForDeltaY;
7827 aEvent->mDeltaZ *= mMultiplierZ[index];
7828
7829 // If the multiplier is 1.0 or -1.0, i.e., it doesn't change the absolute
7830 // value, we should use lineOrPageDelta values which were set by widget.
7831 // Otherwise, we need to compute them from accumulated delta values.
7832 if (!NeedToComputeLineOrPageDelta(aEvent)) {
7833 aEvent->mLineOrPageDeltaX *= static_cast<int32_t>(multiplierForDeltaX);
7834 aEvent->mLineOrPageDeltaY *= static_cast<int32_t>(multiplierForDeltaY);
7835 } else {
7836 aEvent->mLineOrPageDeltaX = 0;
7837 aEvent->mLineOrPageDeltaY = 0;
7838 }
7839
7840 aEvent->mCustomizedByUserPrefs =
7841 ((mMultiplierX[index] != 1.0) || (mMultiplierY[index] != 1.0) ||
7842 (mMultiplierZ[index] != 1.0));
7843}
7844
7845void EventStateManager::WheelPrefs::CancelApplyingUserPrefsFromOverflowDelta(
7846 WidgetWheelEvent* aEvent) {
7847 Index index = GetIndexFor(aEvent);
7848 Init(index);
7849
7850 // XXX If the multiplier pref value is negative, the scroll direction was
7851 // changed and caused to scroll different direction. In such case,
7852 // this method reverts the sign of overflowDelta. Does it make widget
7853 // happy? Although, widget can know the pref applied delta values by
7854 // referrencing the deltaX and deltaY of the event.
7855
7856 double multiplierForDeltaX = 1.0, multiplierForDeltaY = 1.0;
7857 GetMultiplierForDeltaXAndY(aEvent, index, &multiplierForDeltaX,
7858 &multiplierForDeltaY);
7859 if (multiplierForDeltaX) {
7860 aEvent->mOverflowDeltaX /= multiplierForDeltaX;
7861 }
7862 if (multiplierForDeltaY) {
7863 aEvent->mOverflowDeltaY /= multiplierForDeltaY;
7864 }
7865}
7866
7867EventStateManager::WheelPrefs::Action
7868EventStateManager::WheelPrefs::ComputeActionFor(
7869 const WidgetWheelEvent* aEvent) {
7870 Index index = GetIndexFor(aEvent);
7871 Init(index);
7872
7873 bool deltaXPreferred = (Abs(aEvent->mDeltaX) > Abs(aEvent->mDeltaY) &&
7874 Abs(aEvent->mDeltaX) > Abs(aEvent->mDeltaZ));
7875 Action* actions = deltaXPreferred ? mOverriddenActionsX : mActions;
7876 if (actions[index] == ACTION_NONE || actions[index] == ACTION_SCROLL ||
7877 actions[index] == ACTION_HORIZONTALIZED_SCROLL) {
7878 return actions[index];
7879 }
7880
7881 // Momentum events shouldn't run special actions.
7882 if (aEvent->mIsMomentum) {
7883 // Use the default action. Note that user might kill the wheel scrolling.
7884 Init(INDEX_DEFAULT);
7885 if (actions[INDEX_DEFAULT] == ACTION_SCROLL ||
7886 actions[INDEX_DEFAULT] == ACTION_HORIZONTALIZED_SCROLL) {
7887 return actions[INDEX_DEFAULT];
7888 }
7889 return ACTION_NONE;
7890 }
7891
7892 return actions[index];
7893}
7894
7895bool EventStateManager::WheelPrefs::NeedToComputeLineOrPageDelta(
7896 const WidgetWheelEvent* aEvent) {
7897 Index index = GetIndexFor(aEvent);
7898 Init(index);
7899
7900 return (mMultiplierX[index] != 1.0 && mMultiplierX[index] != -1.0) ||
7901 (mMultiplierY[index] != 1.0 && mMultiplierY[index] != -1.0);
7902}
7903
7904void EventStateManager::WheelPrefs::GetUserPrefsForEvent(
7905 const WidgetWheelEvent* aEvent, double* aOutMultiplierX,
7906 double* aOutMultiplierY) {
7907 Index index = GetIndexFor(aEvent);
7908 Init(index);
7909
7910 double multiplierForDeltaX = 1.0, multiplierForDeltaY = 1.0;
7911 GetMultiplierForDeltaXAndY(aEvent, index, &multiplierForDeltaX,
7912 &multiplierForDeltaY);
7913 *aOutMultiplierX = multiplierForDeltaX;
7914 *aOutMultiplierY = multiplierForDeltaY;
7915}
7916
7917// static
7918Maybe<layers::APZWheelAction> EventStateManager::APZWheelActionFor(
7919 const WidgetWheelEvent* aEvent) {
7920 if (aEvent->mMessage != eWheel) {
7921 return Nothing();
7922 }
7923 WheelPrefs::Action action =
7924 WheelPrefs::GetInstance()->ComputeActionFor(aEvent);
7925 switch (action) {
7926 case WheelPrefs::ACTION_SCROLL:
7927 case WheelPrefs::ACTION_HORIZONTALIZED_SCROLL:
7928 return Some(layers::APZWheelAction::Scroll);
7929 case WheelPrefs::ACTION_PINCH_ZOOM:
7930 return Some(layers::APZWheelAction::PinchZoom);
7931 default:
7932 return Nothing();
7933 }
7934}
7935
7936// static
7937WheelDeltaAdjustmentStrategy EventStateManager::GetWheelDeltaAdjustmentStrategy(
7938 const WidgetWheelEvent& aEvent) {
7939 if (aEvent.mMessage != eWheel) {
7940 return WheelDeltaAdjustmentStrategy::eNone;
7941 }
7942 switch (WheelPrefs::GetInstance()->ComputeActionFor(&aEvent)) {
7943 case WheelPrefs::ACTION_SCROLL:
7944 if (StaticPrefs::mousewheel_autodir_enabled() && 0 == aEvent.mDeltaZ) {
7945 if (StaticPrefs::mousewheel_autodir_honourroot()) {
7946 return WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour;
7947 }
7948 return WheelDeltaAdjustmentStrategy::eAutoDir;
7949 }
7950 return WheelDeltaAdjustmentStrategy::eNone;
7951 case WheelPrefs::ACTION_HORIZONTALIZED_SCROLL:
7952 return WheelDeltaAdjustmentStrategy::eHorizontalize;
7953 default:
7954 break;
7955 }
7956 return WheelDeltaAdjustmentStrategy::eNone;
7957}
7958
7959void EventStateManager::GetUserPrefsForWheelEvent(
7960 const WidgetWheelEvent* aEvent, double* aOutMultiplierX,
7961 double* aOutMultiplierY) {
7962 WheelPrefs::GetInstance()->GetUserPrefsForEvent(aEvent, aOutMultiplierX,
7963 aOutMultiplierY);
7964}
7965
7966bool EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedX(
7967 const WidgetWheelEvent* aEvent) {
7968 if (StaticPrefs::mousewheel_allow_scrolling_more_than_one_page()) {
7969 return true;
7970 }
7971
7972 Index index = GetIndexFor(aEvent);
7973 Init(index);
7974 return Abs(mMultiplierX[index]) >=
7975 MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
7976}
7977
7978bool EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedY(
7979 const WidgetWheelEvent* aEvent) {
7980 if (StaticPrefs::mousewheel_allow_scrolling_more_than_one_page()) {
7981 return true;
7982 }
7983
7984 Index index = GetIndexFor(aEvent);
7985 Init(index);
7986 return Abs(mMultiplierY[index]) >=
7987 MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
7988}
7989
7990void EventStateManager::UpdateGestureContent(nsIContent* aContent) {
7991 mGestureDownContent = aContent;
7992 mGestureDownFrameOwner = aContent;
7993}
7994
7995void EventStateManager::NotifyContentWillBeRemovedForGesture(
7996 nsIContent& aContent) {
7997 if (!mGestureDownContent) {
7998 return;
7999 }
8000
8001 if (!nsContentUtils::ContentIsFlattenedTreeDescendantOf(mGestureDownContent,
8002 &aContent)) {
8003 return;
8004 }
8005
8006 UpdateGestureContent(aContent.GetFlattenedTreeParent());
8007}
8008
8009} // namespace mozilla