mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 14:54:25 +00:00
moebius#71: DOM - Pointer Events - improvements
https://github.com/MoonchildProductions/moebius/pull/71
This commit is contained in:
+68
-72
@@ -6514,10 +6514,11 @@ nsIPresShell::GetPointerCapturingContent(uint32_t aPointerId)
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId,
|
||||
uint16_t aPointerType, bool aIsPrimary)
|
||||
nsIPresShell::CheckPointerCaptureState(const WidgetPointerEvent* aPointerEvent)
|
||||
{
|
||||
PointerCaptureInfo* captureInfo = GetPointerCaptureInfo(aPointerId);
|
||||
PointerCaptureInfo* captureInfo =
|
||||
GetPointerCaptureInfo(aPointerEvent->pointerId);
|
||||
|
||||
if (captureInfo &&
|
||||
captureInfo->mPendingContent != captureInfo->mOverrideContent) {
|
||||
// cache captureInfo->mPendingContent since it may be changed in the pointer
|
||||
@@ -6525,17 +6526,16 @@ nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId,
|
||||
nsIContent* pendingContent = captureInfo->mPendingContent.get();
|
||||
if (captureInfo->mOverrideContent) {
|
||||
DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ false,
|
||||
aPointerId, aPointerType, aIsPrimary,
|
||||
aPointerEvent,
|
||||
captureInfo->mOverrideContent);
|
||||
}
|
||||
if (pendingContent) {
|
||||
DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ true, aPointerId,
|
||||
aPointerType, aIsPrimary,
|
||||
pendingContent);
|
||||
DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ true,
|
||||
aPointerEvent, pendingContent);
|
||||
}
|
||||
captureInfo->mOverrideContent = pendingContent;
|
||||
if (captureInfo->Empty()) {
|
||||
sPointerCaptureList->Remove(aPointerId);
|
||||
sPointerCaptureList->Remove(aPointerEvent->pointerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6976,37 +6976,30 @@ DispatchPointerFromMouseOrTouch(PresShell* aShell,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class ReleasePointerCaptureCaller
|
||||
class ReleasePointerCaptureCaller final
|
||||
{
|
||||
public:
|
||||
ReleasePointerCaptureCaller() :
|
||||
mPointerId(0),
|
||||
mPointerType(nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN),
|
||||
mIsPrimary(false),
|
||||
mIsSet(false)
|
||||
ReleasePointerCaptureCaller()
|
||||
: mPointerEvent(nullptr)
|
||||
{
|
||||
}
|
||||
~ReleasePointerCaptureCaller()
|
||||
{
|
||||
if (mIsSet) {
|
||||
nsIPresShell::ReleasePointerCapturingContent(mPointerId);
|
||||
nsIPresShell::CheckPointerCaptureState(mPointerId, mPointerType,
|
||||
mIsPrimary);
|
||||
if (mPointerEvent) {
|
||||
nsIPresShell::ReleasePointerCapturingContent(mPointerEvent->pointerId);
|
||||
nsIPresShell::CheckPointerCaptureState(mPointerEvent);
|
||||
}
|
||||
}
|
||||
void SetTarget(uint32_t aPointerId, uint16_t aPointerType, bool aIsPrimary)
|
||||
|
||||
void SetTarget(const WidgetPointerEvent* aPointerEvent)
|
||||
{
|
||||
mPointerId = aPointerId;
|
||||
mPointerType = aPointerType;
|
||||
mIsPrimary = aIsPrimary;
|
||||
mIsSet = true;
|
||||
MOZ_ASSERT(aPointerEvent);
|
||||
mPointerEvent = aPointerEvent;
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t mPointerId;
|
||||
uint16_t mPointerType;
|
||||
bool mIsPrimary;
|
||||
bool mIsSet;
|
||||
// This is synchronously used inside PresShell::HandleEvent.
|
||||
const WidgetPointerEvent* mPointerEvent;
|
||||
};
|
||||
|
||||
static bool
|
||||
@@ -7719,9 +7712,7 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
||||
nsWeakFrame frameKeeper(frame);
|
||||
// Handle pending pointer capture before any pointer events except
|
||||
// gotpointercapture / lostpointercapture.
|
||||
CheckPointerCaptureState(pointerEvent->pointerId,
|
||||
pointerEvent->inputSource,
|
||||
pointerEvent->mIsPrimary);
|
||||
CheckPointerCaptureState(pointerEvent);
|
||||
// Prevent application crashes, in case damaged frame.
|
||||
if (!frameKeeper.IsAlive()) {
|
||||
frame = nullptr;
|
||||
@@ -7742,33 +7733,29 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
||||
}
|
||||
}
|
||||
|
||||
if (aEvent->mClass == ePointerEventClass &&
|
||||
aEvent->mMessage != ePointerDown) {
|
||||
if (WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent()) {
|
||||
uint32_t pointerId = pointerEvent->pointerId;
|
||||
// Mouse events should be fired to the same target as their mapped pointer
|
||||
// events
|
||||
if ((aEvent->mClass == ePointerEventClass ||
|
||||
aEvent->mClass == eMouseEventClass) &&
|
||||
aEvent->mMessage != ePointerDown && aEvent->mMessage != eMouseDown) {
|
||||
if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
|
||||
uint32_t pointerId = mouseEvent->pointerId;
|
||||
nsIContent* pointerCapturingContent =
|
||||
GetPointerCapturingContent(pointerId);
|
||||
|
||||
if (pointerCapturingContent) {
|
||||
if (nsIFrame* capturingFrame = pointerCapturingContent->GetPrimaryFrame()) {
|
||||
// If pointer capture is set, we should suppress
|
||||
// pointerover/pointerenter events for all elements except element
|
||||
// which have pointer capture. (Code in EventStateManager)
|
||||
pointerEvent->retargetedByPointerCapture =
|
||||
frame && frame->GetContent() &&
|
||||
!nsContentUtils::ContentIsDescendantOf(frame->GetContent(),
|
||||
pointerCapturingContent);
|
||||
frame = capturingFrame;
|
||||
}
|
||||
|
||||
if (pointerEvent->mMessage == ePointerUp ||
|
||||
pointerEvent->mMessage == ePointerCancel) {
|
||||
if (aEvent->mMessage == ePointerUp ||
|
||||
aEvent->mMessage == ePointerCancel) {
|
||||
// Implicitly releasing capture for given pointer.
|
||||
// ePointerLostCapture should be send after ePointerUp or
|
||||
// ePointerCancel.
|
||||
releasePointerCaptureCaller.SetTarget(pointerId,
|
||||
pointerEvent->inputSource,
|
||||
pointerEvent->mIsPrimary);
|
||||
WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent();
|
||||
MOZ_ASSERT(pointerEvent);
|
||||
releasePointerCaptureCaller.SetTarget(pointerEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8340,35 +8327,44 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsIPresShell::DispatchGotOrLostPointerCaptureEvent(bool aIsGotCapture,
|
||||
uint32_t aPointerId,
|
||||
uint16_t aPointerType,
|
||||
bool aIsPrimary,
|
||||
nsIContent* aCaptureTarget)
|
||||
/* static */ void
|
||||
nsIPresShell::DispatchGotOrLostPointerCaptureEvent(
|
||||
bool aIsGotCapture,
|
||||
const WidgetPointerEvent* aPointerEvent,
|
||||
nsIContent* aCaptureTarget)
|
||||
{
|
||||
PointerEventInit init;
|
||||
init.mPointerId = aPointerId;
|
||||
init.mBubbles = true;
|
||||
ConvertPointerTypeToString(aPointerType, init.mPointerType);
|
||||
init.mIsPrimary = aIsPrimary;
|
||||
RefPtr<mozilla::dom::PointerEvent> event;
|
||||
event = PointerEvent::Constructor(aCaptureTarget,
|
||||
aIsGotCapture
|
||||
? NS_LITERAL_STRING("gotpointercapture")
|
||||
: NS_LITERAL_STRING("lostpointercapture"),
|
||||
init);
|
||||
if (event) {
|
||||
nsIDocument* targetDoc = aCaptureTarget->OwnerDoc();
|
||||
nsCOMPtr<nsIPresShell> shell = targetDoc->GetShell();
|
||||
NS_ENSURE_TRUE_VOID(shell);
|
||||
|
||||
if (!aIsGotCapture && !aCaptureTarget->IsInUncomposedDoc()) {
|
||||
// If the capturing element was removed from the DOM tree, fire
|
||||
// ePointerLostCapture at the document.
|
||||
PointerEventInit init;
|
||||
init.mPointerId = aPointerEvent->pointerId;
|
||||
init.mBubbles = true;
|
||||
init.mComposed = true;
|
||||
ConvertPointerTypeToString(aPointerEvent->inputSource, init.mPointerType);
|
||||
init.mIsPrimary = aPointerEvent->mIsPrimary;
|
||||
RefPtr<mozilla::dom::PointerEvent> event;
|
||||
event = PointerEvent::Constructor(aCaptureTarget,
|
||||
NS_LITERAL_STRING("lostpointercapture"),
|
||||
init);
|
||||
bool dummy;
|
||||
// If the capturing element was removed from the DOM tree,
|
||||
// lostpointercapture event should be fired at the document.
|
||||
if (!aIsGotCapture && !aCaptureTarget->IsInUncomposedDoc()) {
|
||||
aCaptureTarget->OwnerDoc()->DispatchEvent(event->InternalDOMEvent(),
|
||||
&dummy);
|
||||
} else {
|
||||
aCaptureTarget->DispatchEvent(event->InternalDOMEvent(), &dummy);
|
||||
}
|
||||
targetDoc->DispatchEvent(event->InternalDOMEvent(), &dummy);
|
||||
return;
|
||||
}
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
WidgetPointerEvent localEvent(aPointerEvent->IsTrusted(),
|
||||
aIsGotCapture ? ePointerGotCapture :
|
||||
ePointerLostCapture,
|
||||
aPointerEvent->mWidget);
|
||||
localEvent.AssignPointerEventData(*aPointerEvent, true);
|
||||
nsresult rv = shell->HandleEventWithTarget(
|
||||
&localEvent,
|
||||
aCaptureTarget->GetPrimaryFrame(),
|
||||
aCaptureTarget, &status);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
||||
Reference in New Issue
Block a user