From d8bbc7858622b6d9c278469aab701ca0b609cddf Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:35:49 +0200 Subject: Merging upstream version 126.0. Signed-off-by: Daniel Baumann --- dom/events/Clipboard.cpp | 5 + dom/events/EventDispatcher.cpp | 29 ++- dom/events/EventListenerManager.cpp | 41 +--- dom/events/EventNameList.h | 5 +- dom/events/EventStateManager.cpp | 243 ++++++++++++++++----- dom/events/EventStateManager.h | 10 +- dom/events/InvokeEvent.cpp | 8 +- dom/events/PointerEventHandler.cpp | 50 ++++- dom/events/PointerEventHandler.h | 12 +- dom/events/TextEvent.cpp | 68 ++++++ dom/events/TextEvent.h | 46 ++++ dom/events/moz.build | 2 + dom/events/test/clipboard/mochitest.toml | 7 + .../test/clipboard/test_async_clipboard.xhtml | 10 +- .../test_async_clipboard_datatransfer.html | 89 ++++++++ dom/events/test/mochitest.toml | 2 - dom/events/test/pointerevents/mochitest.toml | 15 -- ...ge-touch-action-onpointerdown_touch-manual.html | 39 ---- .../test_wpt_pointerevent_constructor.html | 26 --- ...st_wpt_pointerevent_pointerId_scope-manual.html | 27 --- ...ge-touch-action-onpointerdown_touch-manual.html | 135 ------------ .../wpt/pointerevent_constructor.html | 106 --------- .../wpt/pointerevent_pointerId_scope-manual.html | 82 ------- dom/events/test/test_all_synthetic_events.html | 10 +- dom/events/test/test_eventctors.html | 22 ++ dom/events/test/test_marquee_events.html | 31 --- 26 files changed, 523 insertions(+), 597 deletions(-) create mode 100644 dom/events/TextEvent.cpp create mode 100644 dom/events/TextEvent.h create mode 100644 dom/events/test/clipboard/test_async_clipboard_datatransfer.html delete mode 100644 dom/events/test/pointerevents/test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html delete mode 100644 dom/events/test/pointerevents/test_wpt_pointerevent_constructor.html delete mode 100644 dom/events/test/pointerevents/test_wpt_pointerevent_pointerId_scope-manual.html delete mode 100644 dom/events/test/pointerevents/wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html delete mode 100644 dom/events/test/pointerevents/wpt/pointerevent_constructor.html delete mode 100644 dom/events/test/pointerevents/wpt/pointerevent_pointerId_scope-manual.html delete mode 100644 dom/events/test/test_marquee_events.html (limited to 'dom/events') diff --git a/dom/events/Clipboard.cpp b/dom/events/Clipboard.cpp index b163bc816f..b797f93961 100644 --- a/dom/events/Clipboard.cpp +++ b/dom/events/Clipboard.cpp @@ -132,6 +132,11 @@ class ClipboardGetCallbackForRead final : public ClipboardGetCallback { } RefPtr p(std::move(mPromise)); + if (entries.IsEmpty()) { + p->MaybeResolve(nsTArray>{}); + return NS_OK; + } + // We currently only support one clipboard item. p->MaybeResolve( AutoTArray, 1>{MakeRefPtr( diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp index dd3de015b4..61e5adf6f1 100644 --- a/dom/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -47,6 +47,7 @@ #include "mozilla/dom/SimpleGestureEvent.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/StorageEvent.h" +#include "mozilla/dom/TextEvent.h" #include "mozilla/dom/TimeEvent.h" #include "mozilla/dom/TouchEvent.h" #include "mozilla/dom/TransitionEvent.h" @@ -1141,9 +1142,8 @@ nsresult EventDispatcher::Dispatch(EventTarget* aTarget, if (!postVisitor.mDOMEvent) { // This is tiny bit slow, but happens only once per event. // Similar code also in EventListenerManager. - nsCOMPtr et = aEvent->mOriginalTarget; - RefPtr event = - EventDispatcher::CreateEvent(et, aPresContext, aEvent, u""_ns); + RefPtr event = EventDispatcher::CreateEvent( + aEvent->mOriginalTarget, aPresContext, aEvent, u""_ns); event.swap(postVisitor.mDOMEvent); } nsAutoString typeStr; @@ -1151,12 +1151,11 @@ nsresult EventDispatcher::Dispatch(EventTarget* aTarget, AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING( "EventDispatcher::Dispatch", OTHER, typeStr); - nsCOMPtr docShell; - docShell = nsContentUtils::GetDocShellForEventTarget(aEvent->mTarget); MarkerInnerWindowId innerWindowId; - if (nsCOMPtr inner = - do_QueryInterface(aEvent->mTarget->GetOwnerGlobal())) { - innerWindowId = MarkerInnerWindowId{inner->WindowID()}; + if (nsIGlobalObject* global = aEvent->mTarget->GetOwnerGlobal()) { + if (nsPIDOMWindowInner* inner = global->GetAsInnerWindow()) { + innerWindowId = MarkerInnerWindowId{inner->WindowID()}; + } } struct DOMEventMarker { @@ -1206,7 +1205,7 @@ nsresult EventDispatcher::Dispatch(EventTarget* aTarget, auto startTime = TimeStamp::Now(); profiler_add_marker("DOMEvent", geckoprofiler::category::DOM, - {MarkerTiming::IntervalStart(), + {MarkerTiming::IntervalStart(startTime), MarkerInnerWindowId(innerWindowId)}, DOMEventMarker{}, typeStr, target, startTime, aEvent->mTimeStamp); @@ -1406,6 +1405,9 @@ nsresult EventDispatcher::DispatchDOMEvent(EventTarget* aTarget, case eEditorInputEventClass: return NS_NewDOMInputEvent(aOwner, aPresContext, aEvent->AsEditorInputEvent()); + case eLegacyTextEventClass: + return NS_NewDOMTextEvent(aOwner, aPresContext, + aEvent->AsLegacyTextEvent()); case eDragEventClass: return NS_NewDOMDragEvent(aOwner, aPresContext, aEvent->AsDragEvent()); case eClipboardEventClass: @@ -1450,10 +1452,15 @@ nsresult EventDispatcher::DispatchDOMEvent(EventTarget* aTarget, if (aEventType.LowerCaseEqualsLiteral("keyboardevent")) { return NS_NewDOMKeyboardEvent(aOwner, aPresContext, nullptr); } - if (aEventType.LowerCaseEqualsLiteral("compositionevent") || - aEventType.LowerCaseEqualsLiteral("textevent")) { + if (aEventType.LowerCaseEqualsLiteral("compositionevent")) { return NS_NewDOMCompositionEvent(aOwner, aPresContext, nullptr); } + if (aEventType.LowerCaseEqualsLiteral("textevent")) { + if (!StaticPrefs::dom_events_textevent_enabled()) { + return NS_NewDOMCompositionEvent(aOwner, aPresContext, nullptr); + } + return NS_NewDOMTextEvent(aOwner, aPresContext, nullptr); + } if (aEventType.LowerCaseEqualsLiteral("mutationevent") || aEventType.LowerCaseEqualsLiteral("mutationevents")) { return NS_NewDOMMutationEvent(aOwner, aPresContext, nullptr); diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index 269ccd9de7..72d4eb1b30 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -455,27 +455,6 @@ void EventListenerManager::AddEventListenerInternal( window->SetHasFormSelectEventListeners(); } break; - case eMarqueeStart: - if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) { - if (Document* doc = window->GetExtantDoc()) { - doc->SetUseCounter(eUseCounter_custom_onstart); - } - } - break; - case eMarqueeBounce: - if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) { - if (Document* doc = window->GetExtantDoc()) { - doc->SetUseCounter(eUseCounter_custom_onbounce); - } - } - break; - case eMarqueeFinish: - if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) { - if (Document* doc = window->GetExtantDoc()) { - doc->SetUseCounter(eUseCounter_custom_onfinish); - } - } - break; case eScrollPortOverflow: if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) { if (Document* doc = window->GetExtantDoc()) { @@ -608,18 +587,6 @@ void EventListenerManager::AddEventListenerInternal( nsPrintfCString("resolvedEventMessage=%s", ToChar(resolvedEventMessage)) .get()); - NS_ASSERTION(aTypeAtom != nsGkAtoms::onstart, - nsPrintfCString("resolvedEventMessage=%s", - ToChar(resolvedEventMessage)) - .get()); - NS_ASSERTION(aTypeAtom != nsGkAtoms::onbounce, - nsPrintfCString("resolvedEventMessage=%s", - ToChar(resolvedEventMessage)) - .get()); - NS_ASSERTION(aTypeAtom != nsGkAtoms::onfinish, - nsPrintfCString("resolvedEventMessage=%s", - ToChar(resolvedEventMessage)) - .get()); NS_ASSERTION(aTypeAtom != nsGkAtoms::onoverflow, nsPrintfCString("resolvedEventMessage=%s", ToChar(resolvedEventMessage)) @@ -1417,10 +1384,10 @@ already_AddRefed EventListenerManager::WindowFromListener( if (global) { innerWindow = global->GetAsInnerWindow(); // Can be nullptr } - } else { + } else if (mTarget) { // This ensures `window.event` can be set properly for // nsWindowRoot to handle KeyPress event. - if (aListener && aTypeAtom == nsGkAtoms::onkeypress && mTarget && + if (aListener && aTypeAtom == nsGkAtoms::onkeypress && mTarget->IsRootWindow()) { nsPIWindowRoot* root = mTarget->AsWindowRoot(); if (nsPIDOMWindowOuter* outerWindow = root->GetWindow()) { @@ -1431,7 +1398,9 @@ already_AddRefed EventListenerManager::WindowFromListener( // listener->mListener.GetXPCOMCallback(). // In most cases, it would be the same as for // the target, so let's do that. - innerWindow = GetInnerWindowForTarget(); // Can be nullptr + if (nsIGlobalObject* global = mTarget->GetOwnerGlobal()) { + innerWindow = global->GetAsInnerWindow(); + } } } } diff --git a/dom/events/EventNameList.h b/dom/events/EventNameList.h index 92c76d000e..185f75f2bc 100644 --- a/dom/events/EventNameList.h +++ b/dom/events/EventNameList.h @@ -150,7 +150,6 @@ EVENT(abort, eImageAbort, EventNameType_All, eBasicEventClass) EVENT(beforetoggle, eBeforeToggle, EventNameType_HTMLXUL, eBasicEventClass) -EVENT(bounce, eMarqueeBounce, EventNameType_HTMLMarqueeOnly, eBasicEventClass) EVENT(cancel, eCancel, EventNameType_HTMLXUL, eBasicEventClass) EVENT(canplay, eCanPlay, EventNameType_HTML, eBasicEventClass) EVENT(canplaythrough, eCanPlayThrough, EventNameType_HTML, eBasicEventClass) @@ -179,7 +178,6 @@ EVENT(drop, eDrop, EventNameType_HTMLXUL, eDragEventClass) EVENT(durationchange, eDurationChange, EventNameType_HTML, eBasicEventClass) EVENT(emptied, eEmptied, EventNameType_HTML, eBasicEventClass) EVENT(ended, eEnded, EventNameType_HTML, eBasicEventClass) -EVENT(finish, eMarqueeFinish, EventNameType_HTMLMarqueeOnly, eBasicEventClass) EVENT(formdata, eFormData, EventNameType_HTML, eBasicEventClass) EVENT(fullscreenchange, eFullscreenChange, EventNameType_HTML, eBasicEventClass) EVENT(fullscreenerror, eFullscreenError, EventNameType_HTML, eBasicEventClass) @@ -227,6 +225,8 @@ EVENT(gotpointercapture, ePointerGotCapture, EventNameType_All, EVENT(lostpointercapture, ePointerLostCapture, EventNameType_All, ePointerEventClass) EVENT(selectstart, eSelectStart, EventNameType_HTMLXUL, eBasicEventClass) +NON_IDL_EVENT(textInput, eLegacyTextInput, EventNameType_None, + eLegacyTextEventClass) EVENT(contextlost, eContextLost, EventNameType_HTML, eBasicEventClass) EVENT(contextrestored, eContextRestored, EventNameType_HTML, eBasicEventClass) @@ -246,7 +246,6 @@ EVENT(seeking, eSeeking, EventNameType_HTML, eBasicEventClass) EVENT(select, eFormSelect, EventNameType_HTMLXUL, eBasicEventClass) EVENT(slotchange, eSlotChange, EventNameType_All, eBasicEventClass) EVENT(stalled, eStalled, EventNameType_HTML, eBasicEventClass) -EVENT(start, eMarqueeStart, EventNameType_HTMLMarqueeOnly, eBasicEventClass) EVENT(submit, eFormSubmit, EventNameType_HTMLXUL, eBasicEventClass) EVENT(suspend, eSuspend, EventNameType_HTML, eBasicEventClass) EVENT(timeupdate, eTimeUpdate, EventNameType_HTML, eBasicEventClass) diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index 0ae756211b..3c24cdb30a 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -227,6 +227,9 @@ static nsINode* GetCommonAncestorForMouseUp( return parent; } +LazyLogModule sMouseBoundaryLog("MouseBoundaryEvents"); +LazyLogModule sPointerBoundaryLog("PointerBoundaryEvents"); + /******************************************************************/ /* mozilla::UITimerCallback */ /******************************************************************/ @@ -264,8 +267,8 @@ UITimerCallback::Notify(nsITimer* aTimer) { if (XRE_IsParentProcess()) { hal::BatteryInformation batteryInfo; hal::GetCurrentBatteryInformation(&batteryInfo); - glean::power_battery::percentage_when_user_active.AccumulateSamples( - {uint64_t(batteryInfo.level() * 100)}); + glean::power_battery::percentage_when_user_active.AccumulateSingleSample( + uint64_t(batteryInfo.level() * 100)); } } mPreviousCount = gMouseOrKeyboardEventCounter; @@ -282,10 +285,6 @@ UITimerCallback::GetName(nsACString& aName) { /* mozilla::OverOutElementsWrapper */ /******************************************************************/ -OverOutElementsWrapper::OverOutElementsWrapper() : mLastOverFrame(nullptr) {} - -OverOutElementsWrapper::~OverOutElementsWrapper() = default; - NS_IMPL_CYCLE_COLLECTION(OverOutElementsWrapper, mDeepestEnterEventTarget, mDispatchingOverEventTarget, mDispatchingOutOrDeepestLeaveEventTarget) @@ -296,6 +295,116 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(OverOutElementsWrapper) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END +void OverOutElementsWrapper::ContentRemoved(nsIContent& aContent) { + if (!mDeepestEnterEventTarget) { + return; + } + + if (!nsContentUtils::ContentIsFlattenedTreeDescendantOf( + mDeepestEnterEventTarget, &aContent)) { + return; + } + + LogModule* const logModule = mType == BoundaryEventType::Mouse + ? sMouseBoundaryLog + : sPointerBoundaryLog; + + if (!StaticPrefs:: + dom_events_mouse_pointer_boundary_keep_enter_targets_after_over_target_removed()) { + MOZ_LOG(logModule, LogLevel::Info, + ("The last \"over\" event target (%p) is removed", + mDeepestEnterEventTarget.get())); + mDeepestEnterEventTarget = nullptr; + return; + } + + if (mDispatchingOverEventTarget && + (mDeepestEnterEventTarget == mDispatchingOverEventTarget || + nsContentUtils::ContentIsFlattenedTreeDescendantOf( + mDispatchingOverEventTarget, &aContent))) { + if (mDispatchingOverEventTarget == + mDispatchingOutOrDeepestLeaveEventTarget) { + MOZ_LOG(logModule, LogLevel::Info, + ("The dispatching \"%s\" event target (%p) is removed", + mDeepestEnterEventTargetIsOverEventTarget ? "out" : "leave", + mDispatchingOutOrDeepestLeaveEventTarget.get())); + mDispatchingOutOrDeepestLeaveEventTarget = nullptr; + } + MOZ_LOG(logModule, LogLevel::Info, + ("The dispatching \"over\" event target (%p) is removed", + mDispatchingOverEventTarget.get())); + mDispatchingOverEventTarget = nullptr; + } + if (mDispatchingOutOrDeepestLeaveEventTarget && + (mDeepestEnterEventTarget == mDispatchingOutOrDeepestLeaveEventTarget || + nsContentUtils::ContentIsFlattenedTreeDescendantOf( + mDispatchingOutOrDeepestLeaveEventTarget, &aContent))) { + MOZ_LOG(logModule, LogLevel::Info, + ("The dispatching \"%s\" event target (%p) is removed", + mDeepestEnterEventTargetIsOverEventTarget ? "out" : "leave", + mDispatchingOutOrDeepestLeaveEventTarget.get())); + mDispatchingOutOrDeepestLeaveEventTarget = nullptr; + } + MOZ_LOG(logModule, LogLevel::Info, + ("The last \"%s\" event target (%p) is removed and now the last " + "deepest enter target becomes %s(%p)", + mDeepestEnterEventTargetIsOverEventTarget ? "over" : "enter", + mDeepestEnterEventTarget.get(), + aContent.GetFlattenedTreeParent() + ? ToString(*aContent.GetFlattenedTreeParent()).c_str() + : "nullptr", + aContent.GetFlattenedTreeParent())); + mDeepestEnterEventTarget = aContent.GetFlattenedTreeParent(); + mDeepestEnterEventTargetIsOverEventTarget = false; +} + +void OverOutElementsWrapper::DidDispatchOverAndEnterEvent( + nsIContent* aOriginalOverTargetInComposedDoc) { + mDispatchingOverEventTarget = nullptr; + + // Pointer Events define that once the `pointerover` event target is removed + // from the tree, `pointerout` should not be fired on that and the closest + // connected ancestor at the target removal should be kept as the deepest + // `pointerleave` target. Therefore, we don't need the special handling for + // `pointerout` event target if the last `pointerover` target is temporarily + // removed from the tree. + if (mType == OverOutElementsWrapper::BoundaryEventType::Pointer) { + return; + } + + // Assume that the caller checks whether aOriginalOverTarget is in the + // original document. If we don't enable the strict mouse/pointer event + // boundary event dispatching by the pref (see below), + // mDeepestEnterEventTarget is set to nullptr when the last "over" target is + // removed. Therefore, we cannot check whether aOriginalOverTarget is in the + // original document here. + if (!aOriginalOverTargetInComposedDoc) { + return; + } + MOZ_ASSERT_IF(mDeepestEnterEventTarget, + mDeepestEnterEventTarget->GetComposedDoc() == + aOriginalOverTargetInComposedDoc->GetComposedDoc()); + // If the "mouseover" event target is removed temporarily while we're + // dispatching "mouseover" and "mouseenter" events and the target gets back + // under the deepest enter event target, we should restore the "mouseover" + // target. + if ((!StaticPrefs:: + dom_events_mouse_pointer_boundary_keep_enter_targets_after_over_target_removed() && + !mDeepestEnterEventTarget) || + (!mDeepestEnterEventTargetIsOverEventTarget && mDeepestEnterEventTarget && + nsContentUtils::ContentIsFlattenedTreeDescendantOf( + aOriginalOverTargetInComposedDoc, mDeepestEnterEventTarget))) { + mDeepestEnterEventTarget = aOriginalOverTargetInComposedDoc; + mDeepestEnterEventTargetIsOverEventTarget = true; + LogModule* const logModule = mType == BoundaryEventType::Mouse + ? sMouseBoundaryLog + : sPointerBoundaryLog; + MOZ_LOG(logModule, LogLevel::Info, + ("The \"over\" event target (%p) is restored", + mDeepestEnterEventTarget.get())); + } +} + /******************************************************************/ /* mozilla::EventStateManager */ /******************************************************************/ @@ -2169,8 +2278,8 @@ void EventStateManager::MaybeFirePointerCancel(WidgetInputEvent* aEvent) { WidgetPointerEvent event(aTouchEvent->IsTrusted(), ePointerCancel, aTouchEvent->mWidget); - PointerEventHandler::InitPointerEventFromTouch( - event, *aTouchEvent, *aTouchEvent->mTouches[0], true); + PointerEventHandler::InitPointerEventFromTouch(event, *aTouchEvent, + *aTouchEvent->mTouches[0]); event.convertToPointer = false; presShell->HandleEventWithTarget(&event, targetFrame, content, &status); @@ -3453,6 +3562,13 @@ void EventStateManager::PostHandleKeyboardEvent( } } +static bool NeedsActiveContentChange(const WidgetMouseEvent* aMouseEvent) { + // If the mouse event is a synthesized mouse event due to a touch, do + // not set/clear the activation state. Element activation is handled by APZ. + return !aMouseEvent || + aMouseEvent->mInputSource != MouseEvent_Binding::MOZ_SOURCE_TOUCH; +} + nsresult EventStateManager::PostHandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent, nsIFrame* aTargetFrame, @@ -3696,7 +3812,9 @@ nsresult EventStateManager::PostHandleEvent(nsPresContext* aPresContext, } // XXX Why do we always set this is active? Active window may be changed // by a mousedown event listener. - SetActiveManager(this, activeContent); + if (NeedsActiveContentChange(mouseEvent)) { + SetActiveManager(this, activeContent); + } } break; case ePointerCancel: case ePointerUp: { @@ -3724,10 +3842,7 @@ nsresult EventStateManager::PostHandleEvent(nsPresContext* aPresContext, PresShell::ReleaseCapturingContent(); WidgetMouseEvent* mouseUpEvent = aEvent->AsMouseEvent(); - // If the mouseup event is a synthesized mouse event due to a touch, do - // not clear the activation state. Element activation is handled by APZ. - if (!mouseUpEvent || mouseUpEvent->mInputSource != - dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH) { + if (NeedsActiveContentChange(mouseUpEvent)) { ClearGlobalActiveContent(this); } if (mouseUpEvent && EventCausesClickEvents(*mouseUpEvent)) { @@ -4803,6 +4918,10 @@ class EnterLeaveDispatcher { void EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent, nsIContent* aMovingInto) { + const bool isPointer = aMouseEvent->mClass == ePointerEventClass; + LogModule* const logModule = + isPointer ? sPointerBoundaryLog : sMouseBoundaryLog; + RefPtr wrapper = GetWrapperByEventID(aMouseEvent); // If there is no deepest "leave" event target, that means the last "over" @@ -4816,6 +4935,11 @@ void EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent, return; } + MOZ_LOG(logModule, LogLevel::Info, + ("NotifyMouseOut: the source event is %s (IsReal()=%s)", + ToChar(aMouseEvent->mMessage), + aMouseEvent->IsReal() ? "true" : "false")); + // XXX If a content node is a container of remove content, it should be // replaced with them and its children should not be visible. Therefore, // if the deepest "enter" target is not the last "over" target, i.e., the @@ -4829,6 +4953,10 @@ void EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent, if (RefPtr presContext = docshell->GetPresContext()) { EventStateManager* kidESM = presContext->EventStateManager(); // Not moving into any element in this subdocument + MOZ_LOG(logModule, LogLevel::Info, + ("Notifying child EventStateManager (%p) of \"out\" " + "event...", + kidESM)); kidESM->NotifyMouseOut(aMouseEvent, nullptr); } } @@ -4846,7 +4974,6 @@ void EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent, // hover state itself, and we have optimizations for hover switching between // two nearby elements both deep in the DOM tree that would be defeated by // switching the hover state to null here. - bool isPointer = aMouseEvent->mClass == ePointerEventClass; if (!aMovingInto && !isPointer) { // Unset :hover SetContentState(nullptr, ElementState::HOVER); @@ -4859,12 +4986,27 @@ void EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent, // "out" events hould be fired only when the deepest "leave" event target // is the last "over" event target. if (nsCOMPtr outEventTarget = wrapper->GetOutEventTarget()) { + MOZ_LOG(logModule, LogLevel::Info, + ("Dispatching %s event to %s (%p)", + isPointer ? "ePointerOut" : "eMouseOut", + outEventTarget ? ToString(*outEventTarget).c_str() : "nullptr", + outEventTarget.get())); DispatchMouseOrPointerEvent(aMouseEvent, isPointer ? ePointerOut : eMouseOut, outEventTarget, aMovingInto); } + + MOZ_LOG(logModule, LogLevel::Info, + ("Dispatching %s event to %s (%p) and its ancestors", + isPointer ? "ePointerLeave" : "eMouseLeave", + wrapper->GetDeepestLeaveEventTarget() + ? ToString(*wrapper->GetDeepestLeaveEventTarget()).c_str() + : "nullptr", + wrapper->GetDeepestLeaveEventTarget())); leaveDispatcher.Dispatch(); + MOZ_LOG(logModule, LogLevel::Info, + ("Dispatched \"out\" and/or \"leave\" events")); wrapper->DidDispatchOutAndOrLeaveEvent(); } @@ -4884,6 +5026,10 @@ void EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent, nsIContent* aContent) { NS_ASSERTION(aContent, "Mouse must be over something"); + const bool isPointer = aMouseEvent->mClass == ePointerEventClass; + LogModule* const logModule = + isPointer ? sPointerBoundaryLog : sMouseBoundaryLog; + RefPtr wrapper = GetWrapperByEventID(aMouseEvent); // If we have next "out" event target and it's the new "over" target, we don't @@ -4897,6 +5043,11 @@ void EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent, return; } + MOZ_LOG(logModule, LogLevel::Info, + ("NotifyMouseOver: the source event is %s (IsReal()=%s)", + ToChar(aMouseEvent->mMessage), + aMouseEvent->IsReal() ? "true" : "false")); + // Check to see if we're a subdocument and if so update the parent // document's ESM state to indicate that the mouse is over the // content associated with our subdocument. @@ -4906,6 +5057,10 @@ void EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent, if (PresShell* parentPresShell = parentDoc->GetPresShell()) { RefPtr parentESM = parentPresShell->GetPresContext()->EventStateManager(); + MOZ_LOG(logModule, LogLevel::Info, + ("Notifying parent EventStateManager (%p) of \"over\" " + "event...", + parentESM.get())); parentESM->NotifyMouseOver(aMouseEvent, docContent); } } @@ -4922,8 +5077,6 @@ void EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent, nsCOMPtr deepestLeaveEventTarget = wrapper->GetDeepestLeaveEventTarget(); - bool isPointer = aMouseEvent->mClass == ePointerEventClass; - EnterLeaveDispatcher enterDispatcher(this, aContent, deepestLeaveEventTarget, aMouseEvent, isPointer ? ePointerEnter : eMouseEnter); @@ -4939,12 +5092,26 @@ void EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent, // Fire mouseover // XXX If aContent has already been removed from the DOM tree, what should we // do? At least, dispatching `mouseover` on it is odd. + MOZ_LOG(logModule, LogLevel::Info, + ("Dispatching %s event to %s (%p)", + isPointer ? "ePointerOver" : "eMoustOver", + aContent ? ToString(*aContent).c_str() : "nullptr", aContent)); wrapper->mLastOverFrame = DispatchMouseOrPointerEvent( aMouseEvent, isPointer ? ePointerOver : eMouseOver, aContent, deepestLeaveEventTarget); + + MOZ_LOG(logModule, LogLevel::Info, + ("Dispatching %s event to %s (%p) and its ancestors", + isPointer ? "ePointerEnter" : "eMouseEnter", + aContent ? ToString(*aContent).c_str() : "nullptr", aContent)); enterDispatcher.Dispatch(); - wrapper->DidDispatchOverAndEnterEvent(); + MOZ_LOG(logModule, 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())); + wrapper->DidDispatchOverAndEnterEvent( + aContent->GetComposedDoc() == mDocument ? aContent : nullptr); } // Returns the center point of the window's client area. This is @@ -5135,11 +5302,13 @@ OverOutElementsWrapper* EventStateManager::GetWrapperByEventID( if (!pointer) { MOZ_ASSERT(aEvent->AsMouseEvent() != nullptr); if (!mMouseEnterLeaveHelper) { - mMouseEnterLeaveHelper = new OverOutElementsWrapper(); + mMouseEnterLeaveHelper = new OverOutElementsWrapper( + OverOutElementsWrapper::BoundaryEventType::Mouse); } return mMouseEnterLeaveHelper; } - return mPointersEnterLeaveHelper.GetOrInsertNew(pointer->pointerId); + return mPointersEnterLeaveHelper.GetOrInsertNew( + pointer->pointerId, OverOutElementsWrapper::BoundaryEventType::Pointer); } /* static */ @@ -6895,40 +7064,4 @@ bool EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedY( MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL; } -void OverOutElementsWrapper::ContentRemoved(nsIContent& aContent) { - if (!mDeepestEnterEventTarget) { - return; - } - - if (!nsContentUtils::ContentIsFlattenedTreeDescendantOf( - mDeepestEnterEventTarget, &aContent)) { - return; - } - - if (!StaticPrefs:: - dom_events_mouse_pointer_boundary_keep_enter_targets_after_over_target_removed()) { - mDeepestEnterEventTarget = nullptr; - return; - } - - if (mDispatchingOverEventTarget && - (mDeepestEnterEventTarget == mDispatchingOverEventTarget || - nsContentUtils::ContentIsFlattenedTreeDescendantOf( - mDispatchingOverEventTarget, &aContent))) { - if (mDispatchingOverEventTarget == - mDispatchingOutOrDeepestLeaveEventTarget) { - mDispatchingOutOrDeepestLeaveEventTarget = nullptr; - } - mDispatchingOverEventTarget = nullptr; - } - if (mDispatchingOutOrDeepestLeaveEventTarget && - (mDeepestEnterEventTarget == mDispatchingOutOrDeepestLeaveEventTarget || - nsContentUtils::ContentIsFlattenedTreeDescendantOf( - mDispatchingOutOrDeepestLeaveEventTarget, &aContent))) { - mDispatchingOutOrDeepestLeaveEventTarget = nullptr; - } - mDeepestEnterEventTarget = aContent.GetFlattenedTreeParent(); - mDeepestEnterEventTargetIsOverEventTarget = false; -} - } // namespace mozilla diff --git a/dom/events/EventStateManager.h b/dom/events/EventStateManager.h index b3bb3b5170..a4e709d507 100644 --- a/dom/events/EventStateManager.h +++ b/dom/events/EventStateManager.h @@ -56,10 +56,11 @@ class RemoteDragStartData; } // namespace dom class OverOutElementsWrapper final : public nsISupports { - ~OverOutElementsWrapper(); + ~OverOutElementsWrapper() = default; public: - OverOutElementsWrapper(); + enum class BoundaryEventType : bool { Mouse, Pointer }; + explicit OverOutElementsWrapper(BoundaryEventType aType) : mType(aType) {} NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS(OverOutElementsWrapper) @@ -72,7 +73,8 @@ class OverOutElementsWrapper final : public nsISupports { mDispatchingOverEventTarget = aOverEventTarget; mDeepestEnterEventTargetIsOverEventTarget = true; } - void DidDispatchOverAndEnterEvent() { mDispatchingOverEventTarget = nullptr; } + void DidDispatchOverAndEnterEvent( + nsIContent* aOriginalOverTargetInComposedDoc); [[nodiscard]] bool IsDispatchingOverEventOn( nsIContent* aOverEventTarget) const { MOZ_ASSERT(aOverEventTarget); @@ -135,6 +137,8 @@ class OverOutElementsWrapper final : public nsISupports { // the DOM tree, this is set to nullptr. nsCOMPtr mDispatchingOutOrDeepestLeaveEventTarget; + const BoundaryEventType mType; + // Once the last "over" element is removed from the tree, this is set // to false. Then, mDeepestEnterEventTarget may be an ancestor of the // "over" element which should be the deepest target of next "leave" diff --git a/dom/events/InvokeEvent.cpp b/dom/events/InvokeEvent.cpp index 4b7dc1e6da..3312f8138d 100644 --- a/dom/events/InvokeEvent.cpp +++ b/dom/events/InvokeEvent.cpp @@ -47,9 +47,13 @@ already_AddRefed InvokeEvent::Constructor( Element* InvokeEvent::GetInvoker() { EventTarget* currentTarget = GetCurrentTarget(); if (currentTarget) { + nsINode* currentTargetNode = currentTarget->GetAsNode(); + if (!currentTargetNode) { + return nullptr; + } nsINode* retargeted = nsContentUtils::Retarget( - static_cast(mInvoker), currentTarget->GetAsNode()); - return retargeted->AsElement(); + static_cast(mInvoker), currentTargetNode); + return retargeted ? retargeted->AsElement() : nullptr; } MOZ_ASSERT(!mEvent->mFlags.mIsBeingDispatched); return mInvoker; diff --git a/dom/events/PointerEventHandler.cpp b/dom/events/PointerEventHandler.cpp index ef6f2b12c0..f631b6e494 100644 --- a/dom/events/PointerEventHandler.cpp +++ b/dom/events/PointerEventHandler.cpp @@ -15,6 +15,7 @@ #include "mozilla/dom/BrowserChild.h" #include "mozilla/dom/BrowserParent.h" #include "mozilla/dom/Document.h" +#include "mozilla/dom/DocumentInlines.h" #include "mozilla/dom/MouseEventBinding.h" namespace mozilla { @@ -80,7 +81,8 @@ void PointerEventHandler::UpdateActivePointerState(WidgetMouseEvent* aEvent, // In this case we have to know information about available mouse pointers sActivePointersIds->InsertOrUpdate( aEvent->pointerId, - MakeUnique(false, aEvent->mInputSource, true, nullptr)); + MakeUnique(false, aEvent->mInputSource, true, false, + nullptr)); MaybeCacheSpoofedPointerID(aEvent->mInputSource, aEvent->pointerId); break; @@ -94,6 +96,7 @@ void PointerEventHandler::UpdateActivePointerState(WidgetMouseEvent* aEvent, pointerEvent->pointerId, MakeUnique( true, pointerEvent->mInputSource, pointerEvent->mIsPrimary, + pointerEvent->mFromTouchEvent, aTargetContent ? aTargetContent->OwnerDoc() : nullptr)); MaybeCacheSpoofedPointerID(pointerEvent->mInputSource, pointerEvent->pointerId); @@ -112,7 +115,8 @@ void PointerEventHandler::UpdateActivePointerState(WidgetMouseEvent* aEvent, sActivePointersIds->InsertOrUpdate( pointerEvent->pointerId, MakeUnique(false, pointerEvent->mInputSource, - pointerEvent->mIsPrimary, nullptr)); + pointerEvent->mIsPrimary, + pointerEvent->mFromTouchEvent, nullptr)); } else { sActivePointersIds->Remove(pointerEvent->pointerId); } @@ -314,7 +318,7 @@ void PointerEventHandler::ProcessPointerCaptureForTouch( continue; } WidgetPointerEvent event(aEvent->IsTrusted(), eVoidEvent, aEvent->mWidget); - InitPointerEventFromTouch(event, *aEvent, *touch, i == 0); + InitPointerEventFromTouch(event, *aEvent, *touch); CheckPointerCaptureState(&event); } } @@ -461,11 +465,13 @@ Element* PointerEventHandler::GetPointerCapturingElement( void PointerEventHandler::ReleaseIfCaptureByDescendant(nsIContent* aContent) { // We should check that aChild does not contain pointer capturing elements. // If it does we should release the pointer capture for the elements. - for (const auto& entry : *sPointerCaptureList) { - PointerCaptureInfo* data = entry.GetWeak(); - if (data && data->mPendingElement && - data->mPendingElement->IsInclusiveDescendantOf(aContent)) { - ReleasePointerCaptureById(entry.GetKey()); + if (!sPointerCaptureList->IsEmpty()) { + for (const auto& entry : *sPointerCaptureList) { + PointerCaptureInfo* data = entry.GetWeak(); + if (data && data->mPendingElement && + data->mPendingElement->IsInclusiveDescendantOf(aContent)) { + ReleasePointerCaptureById(entry.GetKey()); + } } } } @@ -546,7 +552,7 @@ void PointerEventHandler::InitPointerEventFromMouse( /* static */ void PointerEventHandler::InitPointerEventFromTouch( WidgetPointerEvent& aPointerEvent, const WidgetTouchEvent& aTouchEvent, - const mozilla::dom::Touch& aTouch, bool aIsPrimary) { + const mozilla::dom::Touch& aTouch) { // Use mButton/mButtons only when mButton got a value (from pen input) int16_t button = aTouchEvent.mMessage == eTouchMove ? MouseButton::eNotPressed : aTouchEvent.mButton != MouseButton::eNotPressed @@ -558,7 +564,10 @@ void PointerEventHandler::InitPointerEventFromTouch( ? aTouchEvent.mButtons : MouseButtonsFlag::ePrimaryFlag; - aPointerEvent.mIsPrimary = aIsPrimary; + // Only the first touch would be the primary pointer. + aPointerEvent.mIsPrimary = aTouchEvent.mMessage == eTouchStart + ? !HasActiveTouchPointer() + : GetPointerPrimaryState(aTouch.Identifier()); aPointerEvent.pointerId = aTouch.Identifier(); aPointerEvent.mRefPoint = aTouch.mRefPoint; aPointerEvent.mModifiers = aTouchEvent.mModifiers; @@ -679,7 +688,7 @@ void PointerEventHandler::DispatchPointerFromMouseOrTouch( WidgetPointerEvent event(touchEvent->IsTrusted(), pointerMessage, touchEvent->mWidget); - InitPointerEventFromTouch(event, *touchEvent, *touch, i == 0); + InitPointerEventFromTouch(event, *touchEvent, *touch); event.convertToPointer = touch->convertToPointer = false; event.mCoalescedWidgetEvents = touch->mCoalescedWidgetEvents; if (aMouseOrTouchEvent->mMessage == eTouchStart) { @@ -739,6 +748,15 @@ void PointerEventHandler::NotifyDestroyPresContext( iter.Remove(); } } + // Clean up active pointer info + for (auto iter = sActivePointersIds->Iter(); !iter.Done(); iter.Next()) { + PointerInfo* data = iter.UserData(); + MOZ_ASSERT(data, "how could we have a null PointerInfo here?"); + if (data->mActiveDocument && + data->mActiveDocument->GetPresContext() == aPresContext) { + iter.Remove(); + } + } } bool PointerEventHandler::IsDragAndDropEnabled(WidgetMouseEvent& aEvent) { @@ -770,6 +788,16 @@ bool PointerEventHandler::GetPointerPrimaryState(uint32_t aPointerId) { return false; } +/* static */ +bool PointerEventHandler::HasActiveTouchPointer() { + for (auto iter = sActivePointersIds->ConstIter(); !iter.Done(); iter.Next()) { + if (iter.Data()->mFromTouchEvent) { + return true; + } + } + return false; +} + /* static */ void PointerEventHandler::DispatchGotOrLostPointerCaptureEvent( bool aIsGotCapture, const WidgetPointerEvent* aPointerEvent, diff --git a/dom/events/PointerEventHandler.h b/dom/events/PointerEventHandler.h index 0211bfe0d8..87b41f9d94 100644 --- a/dom/events/PointerEventHandler.h +++ b/dom/events/PointerEventHandler.h @@ -50,13 +50,16 @@ class PointerInfo final { uint16_t mPointerType; bool mActiveState; bool mPrimaryState; + bool mFromTouchEvent; bool mPreventMouseEventByContent; WeakPtr mActiveDocument; explicit PointerInfo(bool aActiveState, uint16_t aPointerType, - bool aPrimaryState, dom::Document* aActiveDocument) + bool aPrimaryState, bool aFromTouchEvent, + dom::Document* aActiveDocument) : mPointerType(aPointerType), mActiveState(aActiveState), mPrimaryState(aPrimaryState), + mFromTouchEvent(aFromTouchEvent), mPreventMouseEventByContent(false), mActiveDocument(aActiveDocument) {} }; @@ -208,8 +211,7 @@ class PointerEventHandler final { static void InitPointerEventFromTouch(WidgetPointerEvent& aPointerEvent, const WidgetTouchEvent& aTouchEvent, - const mozilla::dom::Touch& aTouch, - bool aIsPrimary); + const mozilla::dom::Touch& aTouch); static bool ShouldGeneratePointerEventFromMouse(WidgetGUIEvent* aEvent) { return aEvent->mMessage == eMouseDown || aEvent->mMessage == eMouseUp || @@ -250,6 +252,10 @@ class PointerEventHandler final { // event with pointerId static bool GetPointerPrimaryState(uint32_t aPointerId); + // HasActiveTouchPointer returns true if there is active pointer event that is + // generated from touch event. + static bool HasActiveTouchPointer(); + MOZ_CAN_RUN_SCRIPT static void DispatchGotOrLostPointerCaptureEvent( bool aIsGotCapture, const WidgetPointerEvent* aPointerEvent, diff --git a/dom/events/TextEvent.cpp b/dom/events/TextEvent.cpp new file mode 100644 index 0000000000..95ed15f8e2 --- /dev/null +++ b/dom/events/TextEvent.cpp @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/BasePrincipal.h" // for nsIPrincipal::IsSystemPrincipal() +#include "mozilla/EventForwards.h" +#include "mozilla/TextEvents.h" +#include "mozilla/dom/DataTransfer.h" +#include "mozilla/dom/TextEvent.h" +#include "nsGlobalWindowInner.h" +#include "nsIPrincipal.h" +#include "nsPresContext.h" + +namespace mozilla::dom { + +TextEvent::TextEvent(EventTarget* aOwner, nsPresContext* aPresContext, + InternalLegacyTextEvent* aEvent) + : UIEvent(aOwner, aPresContext, + aEvent + ? aEvent + : new InternalLegacyTextEvent(false, eVoidEvent, nullptr)) { + NS_ASSERTION(mEvent->mClass == eLegacyTextEventClass, "event type mismatch"); + mEventIsInternal = !aEvent; +} + +void TextEvent::InitTextEvent(const nsAString& typeArg, bool canBubbleArg, + bool cancelableArg, nsGlobalWindowInner* viewArg, + const nsAString& dataArg) { + if (NS_WARN_IF(mEvent->mFlags.mIsBeingDispatched)) { + return; + } + + UIEvent::InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, 0); + + static_cast(mEvent)->mData = dataArg; +} + +void TextEvent::GetData(nsAString& aData, + nsIPrincipal& aSubjectPrincipal) const { + InternalLegacyTextEvent* textEvent = mEvent->AsLegacyTextEvent(); + MOZ_ASSERT(textEvent); + if (mEvent->IsTrusted() && !aSubjectPrincipal.IsSystemPrincipal() && + !StaticPrefs::dom_event_clipboardevents_enabled() && + ExposesClipboardDataOrDataTransfer(textEvent->mInputType)) { + aData.Truncate(); + return; + } + if (!textEvent->mDataTransfer) { + aData = textEvent->mData; + return; + } + textEvent->mDataTransfer->GetData(u"text/plain"_ns, aData, aSubjectPrincipal, + IgnoreErrors()); +} + +} // namespace mozilla::dom + +using namespace mozilla; +using namespace mozilla::dom; + +already_AddRefed NS_NewDOMTextEvent( + EventTarget* aOwner, nsPresContext* aPresContext, + InternalLegacyTextEvent* aEvent) { + RefPtr it = new TextEvent(aOwner, aPresContext, aEvent); + return it.forget(); +} diff --git a/dom/events/TextEvent.h b/dom/events/TextEvent.h new file mode 100644 index 0000000000..0546a24eed --- /dev/null +++ b/dom/events/TextEvent.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_TextEvent_h +#define mozilla_dom_TextEvent_h + +#include "mozilla/dom/UIEvent.h" + +#include "mozilla/dom/TextEventBinding.h" +#include "mozilla/EventForwards.h" + +class nsIPrincipal; + +namespace mozilla::dom { + +class TextEvent : public UIEvent { + public: + TextEvent(EventTarget* aOwner, nsPresContext* aPresContext, + InternalLegacyTextEvent* aEvent); + + NS_INLINE_DECL_REFCOUNTING_INHERITED(TextEvent, UIEvent) + + virtual JSObject* WrapObjectInternal( + JSContext* aCx, JS::Handle aGivenProto) override { + return TextEvent_Binding::Wrap(aCx, this, aGivenProto); + } + + void GetData(nsAString& aData, nsIPrincipal& aSubjectPrincipal) const; + void InitTextEvent(const nsAString& typeArg, bool canBubbleArg, + bool cancelableArg, nsGlobalWindowInner* viewArg, + const nsAString& dataArg); + + protected: + ~TextEvent() = default; +}; + +} // namespace mozilla::dom + +already_AddRefed NS_NewDOMTextEvent( + mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, + mozilla::InternalLegacyTextEvent* aEvent); + +#endif // mozilla_dom_InputEvent_h_ diff --git a/dom/events/moz.build b/dom/events/moz.build index 62e1f7d57b..405bdff895 100644 --- a/dom/events/moz.build +++ b/dom/events/moz.build @@ -94,6 +94,7 @@ EXPORTS.mozilla.dom += [ "SimpleGestureEvent.h", "StorageEvent.h", "TextClause.h", + "TextEvent.h", "Touch.h", "TouchEvent.h", "TransitionEvent.h", @@ -154,6 +155,7 @@ UNIFIED_SOURCES += [ "StorageEvent.cpp", "TextClause.cpp", "TextComposition.cpp", + "TextEvent.cpp", "Touch.cpp", "TouchEvent.cpp", "TransitionEvent.cpp", diff --git a/dom/events/test/clipboard/mochitest.toml b/dom/events/test/clipboard/mochitest.toml index 7829915267..98cbd3ddb5 100644 --- a/dom/events/test/clipboard/mochitest.toml +++ b/dom/events/test/clipboard/mochitest.toml @@ -1,5 +1,12 @@ [DEFAULT] +["test_async_clipboard_datatransfer.html"] +scheme = "https" +skip-if = [ + "headless", # headless doesn't support custom type + "os == 'android'", # android doesn't support custom type +] + ["test_paste_image.html"] skip-if = [ "headless", # Bug 1405869 diff --git a/dom/events/test/clipboard/test_async_clipboard.xhtml b/dom/events/test/clipboard/test_async_clipboard.xhtml index ec54809077..8a882fd24d 100644 --- a/dom/events/test/clipboard/test_async_clipboard.xhtml +++ b/dom/events/test/clipboard/test_async_clipboard.xhtml @@ -74,15 +74,7 @@ }); const items = await navigator.clipboard.read(); - - // Bug 1756955: at least on Ubuntu 20.04, clearing the clipboard leads to - // one item with no types. - if (!items.length || - (items.length == 1 && !items[0].types.length)) { - ok(true, "read() read the right thing from empty clipboard"); - } else { - ok(false, "read() read the wrong thing from empty clipboard"); - } + ok(!items.length, "read() read the right thing from empty clipboard"); } async function testNoContentsReadText() { diff --git a/dom/events/test/clipboard/test_async_clipboard_datatransfer.html b/dom/events/test/clipboard/test_async_clipboard_datatransfer.html new file mode 100644 index 0000000000..ab4151f4f5 --- /dev/null +++ b/dom/events/test/clipboard/test_async_clipboard_datatransfer.html @@ -0,0 +1,89 @@ + + +Test for bug 1756955 + + + + + + + + diff --git a/dom/events/test/mochitest.toml b/dom/events/test/mochitest.toml index 53675a8f49..19a082b1e3 100644 --- a/dom/events/test/mochitest.toml +++ b/dom/events/test/mochitest.toml @@ -448,8 +448,6 @@ skip-if = [ ["test_legacy_touch_api.html"] -["test_marquee_events.html"] - ["test_messageEvent.html"] ["test_messageEvent_init.html"] diff --git a/dom/events/test/pointerevents/mochitest.toml b/dom/events/test/pointerevents/mochitest.toml index 340704f94e..c22e1bdf94 100644 --- a/dom/events/test/pointerevents/mochitest.toml +++ b/dom/events/test/pointerevents/mochitest.toml @@ -126,17 +126,6 @@ skip-if = [ "http2", ] -["test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html"] -support-files = ["wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html"] -disabled = "disabled" - -["test_wpt_pointerevent_constructor.html"] -support-files = ["wpt/pointerevent_constructor.html"] -skip-if = [ - "http3", - "http2", -] - ["test_wpt_pointerevent_drag_interaction-manual.html"] support-files = ["wpt/html/pointerevent_drag_interaction-manual.html"] skip-if = [ @@ -158,10 +147,6 @@ skip-if = [ support-files = ["wpt/pointerevent_multiple_primary_pointers_boundary_events-manual.html"] disabled = "should be investigated" -["test_wpt_pointerevent_pointerId_scope-manual.html"] -support-files = ["wpt/resources/pointerevent_pointerId_scope-iframe.html"] -disabled = "should be investigated" - ["test_wpt_pointerevent_pointercancel_touch-manual.html"] support-files = ["wpt/pointerevent_pointercancel_touch-manual.html"] skip-if = [ diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html deleted file mode 100644 index f95b16c850..0000000000 --- a/dom/events/test/pointerevents/test_wpt_pointerevent_change-touch-action-onpointerdown_touch-manual.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - Test for Bug 1000870 - - - - - - - - - - diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_constructor.html b/dom/events/test/pointerevents/test_wpt_pointerevent_constructor.html deleted file mode 100644 index 058e32a967..0000000000 --- a/dom/events/test/pointerevents/test_wpt_pointerevent_constructor.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - Test for Bug 1000870 - - - - - - - - - - diff --git a/dom/events/test/pointerevents/test_wpt_pointerevent_pointerId_scope-manual.html b/dom/events/test/pointerevents/test_wpt_pointerevent_pointerId_scope-manual.html deleted file mode 100644 index f52bf7fc20..0000000000 --- a/dom/events/test/pointerevents/test_wpt_pointerevent_pointerId_scope-manual.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - Test for Bug 1000870 - - - - - - - - - - diff --git a/dom/events/test/pointerevents/wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html deleted file mode 100644 index 04d56cb7a5..0000000000 --- a/dom/events/test/pointerevents/wpt/pointerevent_change-touch-action-onpointerdown_touch-manual.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - Change touch-action on pointerdown - - - - - - - - -

Pointer Events touch-action attribute support

-

Test Description: Press and hold your touch. Try to scroll text in any direction. - Then release your touch and try to scroll again. Expected: no panning. -

-

Note: this test is for touch-devices only

-
-

- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem - nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat. - Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit - lobortis nisl ut aliquip ex ea commodo consequat. -

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem - nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat. - Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit - lobortis nisl ut aliquip ex ea commodo consequat. -

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem - nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat. - Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit - lobortis nisl ut aliquip ex ea commodo consequat. -

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem - nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat. - Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit - lobortis nisl ut aliquip ex ea commodo consequat. -

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-

Lorem ipsum dolor sit amet...

-
- -

touch-action: auto to none

-
-

The following pointer types were detected: .

-
-
- - \ No newline at end of file diff --git a/dom/events/test/pointerevents/wpt/pointerevent_constructor.html b/dom/events/test/pointerevents/wpt/pointerevent_constructor.html deleted file mode 100644 index b2a779d1f7..0000000000 --- a/dom/events/test/pointerevents/wpt/pointerevent_constructor.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - PointerEvent: Constructor test - - - - - - - - -

PointerEvent: Dispatch custom event

-

Test Description: This test checks if PointerEvent constructor works properly using synthetic pointerover and pointerout events. For valid results, this test must be run without generating real (trusted) pointerover or pointerout events on the black rectangle below.

-
- -
-

The following pointer types were detected: .

-
-
- - diff --git a/dom/events/test/pointerevents/wpt/pointerevent_pointerId_scope-manual.html b/dom/events/test/pointerevents/wpt/pointerevent_pointerId_scope-manual.html deleted file mode 100644 index 3640cb6f6b..0000000000 --- a/dom/events/test/pointerevents/wpt/pointerevent_pointerId_scope-manual.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - Pointer Events pointerdown tests - - - - - - - - - -

Pointer Events pointerdown tests

- Complete the following actions: -
    -
  1. Start with your pointing device outside of black box, then move it into black box. If using touch just press in black box and don't release. -
  2. Move your pointing device into purple box (without leaving the digitizer range if you are using hover supported pen or without releasing touch if using touch). Then move it out of the purple box. -
-
-
- -
-

The following pointer types were detected: .

-

Refresh the page to run the tests again with a different pointer type.

-
-
- - diff --git a/dom/events/test/test_all_synthetic_events.html b/dom/events/test/test_all_synthetic_events.html index d8de1a9148..3a00227f1b 100644 --- a/dom/events/test/test_all_synthetic_events.html +++ b/dom/events/test/test_all_synthetic_events.html @@ -376,6 +376,13 @@ const kEventConstructors = { return new TCPServerSocketEvent(aName, aProps); }, }, + TextEvent : { create (aName, aProps) { + var e = document.createEvent("textevent"); + e.initTextEvent("textInput", aProps.bubbles, aProps.cancelable, + aProps.view, aProps.data); + return e; + }, + }, TimeEvent: { create: null // Cannot create untrusted event from JS }, @@ -477,7 +484,8 @@ function test() { SimpleTest.waitForExplicitFinish(); SpecialPowers.pushPrefEnv( {"set": [["dom.w3c_touch_events.legacy_apis.enabled", true], - ["layout.css.content-visibility.enabled", true]]}, + ["layout.css.content-visibility.enabled", true], + ["dom.events.textevent.enabled", true]]}, function() { test(); SimpleTest.finish(); diff --git a/dom/events/test/test_eventctors.html b/dom/events/test/test_eventctors.html index 01ae59493e..26b9d647bf 100644 --- a/dom/events/test/test_eventctors.html +++ b/dom/events/test/test_eventctors.html @@ -924,6 +924,28 @@ is(e.dataTransfer, null, "InputEvent.dataTransfer should be null in default"); is(e.inputType, "", "InputEvent.inputType should be empty string in default"); is(e.isComposing, false, "InputEvent.isComposing should be false in default"); +// TextEvent +if (SpecialPowers.getBoolPref("dom.events.textevent.enabled")) { + try { + e = new TextEvent(); + ok(false, "TextEvent should not have constructor"); + } catch (exp) { + ok(true, "TextEvent does not have a constructor"); + } + try { + e = new TextEvent("foo"); + ok(false, "TextEvent should not have constructor"); + } catch (exp) { + ok(true, "TextEvent does not have a constructor taking a event type"); + } + try { + e = new TextEvent("foo", {}); + ok(false, "TextEvent should not have constructor"); + } catch (exp) { + ok(true, "TextEvent does not have a constructor taking event type and a dictionary"); + } +} + diff --git a/dom/events/test/test_marquee_events.html b/dom/events/test/test_marquee_events.html deleted file mode 100644 index 22d0eafdf1..0000000000 --- a/dom/events/test/test_marquee_events.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - Test for bug 1425874 - - - - - - - - -- cgit v1.2.3