Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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