Bug Summary

File:root/firefox-clang/dom/events/EventStateManager.cpp
Warning:line 2197, column 11
Access to field 'mMessage' results in a dereference of a null pointer (loaded from variable 'mouseEvent')

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)
;
1
Assuming 'aEvent' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
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)
;
4
Assuming 'aRemoteTarget' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
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)
;
7
Assuming 'aStatus' is non-null
8
Taking false branch
9
Loop condition is false. Exiting loop
2155
2156 BrowserParent* remote = aRemoteTarget;
2157
2158 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
10
'mouseEvent' initialized here
2159 bool isContextMenuKey = mouseEvent && mouseEvent->IsContextMenuKeyEvent();
11
Assuming 'mouseEvent' is null
2160 if (aEvent->mClass == eKeyboardEventClass || isContextMenuKey
12.1
'isContextMenuKey' is false
) {
12
Assuming field 'mClass' is not equal to eKeyboardEventClass
13
Taking false branch
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()) {
14
Taking false branch
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)
;
15
Assuming field 'mMessage' is not equal to ePointerClick
16
Taking false branch
17
Loop condition is false. Exiting loop
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)
;
18
Assuming field 'mMessage' is not equal to ePointerAuxClick
19
Taking false branch
20
Loop condition is false. Exiting loop
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) {
21
Control jumps to 'case eMouseEventClass:' at line 2191
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) {
22
Access to field 'mMessage' results in a dereference of a null pointer (loaded from variable 'mouseEvent')
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)
;
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)
;
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 &&
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) {
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)
;
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 (
4293 // After pointercancel, pointer becomes invalid so we can remove
4294 // relevant helper from table.
4295 pointerEvent->mMessage == 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()) {
4300 GenerateMouseEnterExit(pointerEvent);
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)
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() &&
5362 (aMessage == eMouseLeave || aMessage == eMouseEnter ||
5363 aMessage == eMouseOver || aMessage == eMouseOut)) {
5364 mCurrentTargetContent = nullptr;
5365 nsCOMPtr<Element> pointerLockedElement =
5366 PointerLockManager::GetLockedElement();
5367 if (!pointerLockedElement) {
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 =
5372 mPresContext->GetPrimaryFrameFor(pointerLockedElement);
5373 if (NS_WARN_IF(!pointerLockedFrame)NS_warn_if_impl(!pointerLockedFrame, "!pointerLockedFrame", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5373)
) {
5374 return nullptr;
5375 }
5376 return do_AddRef(pointerLockedFrame->GetNearestWidget());
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;
5505 LogModule* const logModule =
5506 isPointer ? sPointerBoundaryLog : sMouseBoundaryLog;
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()) {
5514 return;
5515 }
5516 // Before firing "out" and/or "leave" events, check for recursion
5517 if (wrapper->IsDispatchingOutEventOnLastOverEventTarget()) {
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)
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 =
5533 do_QueryObject(wrapper->GetDeepestLeaveEventTarget())) {
5534 if (BrowsingContext* bc = flo->GetExtantBrowsingContext()) {
5535 if (nsIDocShell* docshell = bc->GetDocShell()) {
5536 if (RefPtr<nsPresContext> presContext = docshell->GetPresContext()) {
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)
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);
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()) {
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 && (!isPointer || aMouseEvent->InputSourceSupportsHover())) {
5561 // Unset :hover
5562 SetContentState(nullptr, ElementState::HOVER);
5563 }
5564
5565 EnterLeaveDispatcher leaveDispatcher(
5566 this, wrapper->GetDeepestLeaveEventTarget(), aMovingInto, aMouseEvent,
5567 isPointer ? ePointerLeave : eMouseLeave);
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()) {
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)
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(
5578 aMouseEvent, isPointer ? ePointerOut : eMouseOut, outEventTarget,
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;
6003
6004 // Hold onto old target content through the event and reset after.
6005 nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
6006
6007 switch (aMouseEvent->mMessage) {
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) {
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);
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