Bug Summary

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