зеркало из https://github.com/mozilla/gecko-dev.git
Bug 979497 - Once DispatchPointerFromMouseOrTouch is called, aFrame can be deleted. r=smaug
--HG-- extra : rebase_source : 9556dce20748b3b581f8e39df6992513e90f62ff
This commit is contained in:
Родитель
2cfe169d44
Коммит
f60627631d
|
@ -472,6 +472,7 @@ nsresult
|
|||
EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsIContent* aTargetContent,
|
||||
nsEventStatus* aStatus)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aStatus);
|
||||
|
@ -481,6 +482,11 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
NS_WARN_IF_FALSE(!aTargetFrame ||
|
||||
!aTargetFrame->GetContent() ||
|
||||
aTargetFrame->GetContent() == aTargetContent,
|
||||
"aTargetContent should be related with aTargetFrame");
|
||||
|
||||
mCurrentTarget = aTargetFrame;
|
||||
mCurrentTargetContent = nullptr;
|
||||
|
||||
|
@ -507,10 +513,9 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
WheelTransaction::OnEvent(aEvent);
|
||||
|
||||
// Focus events don't necessarily need a frame.
|
||||
if (NS_EVENT_NEEDS_FRAME(aEvent)) {
|
||||
if (!mCurrentTarget) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (!mCurrentTarget && !aTargetContent) {
|
||||
NS_ERROR("mCurrentTarget and aTargetContent are null");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (aEvent->HasDragEventMessage() && sIsPointerLocked) {
|
||||
|
@ -1515,10 +1520,12 @@ EventStateManager::BeginTrackingDragGesture(nsPresContext* aPresContext,
|
|||
// synthesized mouse move event.
|
||||
mGestureDownPoint = inDownEvent->refPoint + inDownEvent->widget->WidgetToScreenOffset();
|
||||
|
||||
inDownFrame->GetContentForEvent(inDownEvent,
|
||||
getter_AddRefs(mGestureDownContent));
|
||||
if (inDownFrame) {
|
||||
inDownFrame->GetContentForEvent(inDownEvent,
|
||||
getter_AddRefs(mGestureDownContent));
|
||||
|
||||
mGestureDownFrameOwner = inDownFrame->GetContent();
|
||||
mGestureDownFrameOwner = inDownFrame->GetContent();
|
||||
}
|
||||
mGestureModifiers = inDownEvent->modifiers;
|
||||
mGestureDownButtons = inDownEvent->buttons;
|
||||
|
||||
|
@ -4397,7 +4404,9 @@ EventStateManager::SetClickCount(nsPresContext* aPresContext,
|
|||
{
|
||||
nsCOMPtr<nsIContent> mouseContent;
|
||||
nsIContent* mouseContentParent = nullptr;
|
||||
mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(mouseContent));
|
||||
if (mCurrentTarget) {
|
||||
mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(mouseContent));
|
||||
}
|
||||
if (mouseContent) {
|
||||
if (mouseContent->IsNodeOfType(nsINode::eTEXT)) {
|
||||
mouseContent = mouseContent->GetParent();
|
||||
|
|
|
@ -94,6 +94,7 @@ public:
|
|||
nsresult PreHandleEvent(nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsIContent* aTargetContent,
|
||||
nsEventStatus* aStatus);
|
||||
|
||||
/* The PostHandleEvent method should contain all system processing which
|
||||
|
|
|
@ -139,10 +139,10 @@ typedef struct CapturingContentInfo {
|
|||
nsIContent* mContent;
|
||||
} CapturingContentInfo;
|
||||
|
||||
// 9d010f90-2d90-471c-b640-038cc350c187
|
||||
// d910f009-d209-74c1-6b04-30c83c051c78
|
||||
#define NS_IPRESSHELL_IID \
|
||||
{ 0x9d010f90, 0x2d90, 0x471c, \
|
||||
{ 0xb6, 0x40, 0x03, 0x8c, 0xc3, 0x50, 0xc1, 0x87 } }
|
||||
{ 0xd910f009, 0xd209, 0x74c1, \
|
||||
{ 0x6b, 0x04, 0x30, 0xc8, 0x3c, 0x05, 0x1c, 0x78 } }
|
||||
|
||||
// debug VerifyReflow flags
|
||||
#define VERIFY_REFLOW_ON 0x01
|
||||
|
@ -1439,7 +1439,8 @@ public:
|
|||
virtual nsresult HandleEvent(nsIFrame* aFrame,
|
||||
mozilla::WidgetGUIEvent* aEvent,
|
||||
bool aDontRetargetEvents,
|
||||
nsEventStatus* aEventStatus) = 0;
|
||||
nsEventStatus* aEventStatus,
|
||||
nsIContent** aTargetContent = nullptr) = 0;
|
||||
virtual bool ShouldIgnoreInvalidation() = 0;
|
||||
/**
|
||||
* Notify that we're going to call Paint with PAINT_LAYERS
|
||||
|
|
|
@ -4584,6 +4584,13 @@ PresShell::ContentRemoved(nsIDocument *aDocument,
|
|||
RestyleForRemove(aContainer->AsElement(), aChild, oldNextSibling);
|
||||
}
|
||||
|
||||
// After removing aChild from tree we should save information about live ancestor
|
||||
if (mPointerEventTarget) {
|
||||
if (nsContentUtils::ContentIsDescendantOf(mPointerEventTarget, aChild)) {
|
||||
mPointerEventTarget = aContainer;
|
||||
}
|
||||
}
|
||||
|
||||
// We should check that aChild does not contain pointer capturing elements.
|
||||
// If it does we should release the pointer capture for the elements.
|
||||
gPointerCaptureList->EnumerateRead(ReleasePointerCaptureFromRemovedContent, aChild);
|
||||
|
@ -6819,7 +6826,8 @@ DispatchPointerFromMouseOrTouch(PresShell* aShell,
|
|||
nsIFrame* aFrame,
|
||||
WidgetGUIEvent* aEvent,
|
||||
bool aDontRetargetEvents,
|
||||
nsEventStatus* aStatus)
|
||||
nsEventStatus* aStatus,
|
||||
nsIContent** aTargetContent)
|
||||
{
|
||||
uint32_t pointerMessage = 0;
|
||||
if (aEvent->mClass == eMouseEventClass) {
|
||||
|
@ -6853,7 +6861,7 @@ DispatchPointerFromMouseOrTouch(PresShell* aShell,
|
|||
mouseEvent->pressure ? mouseEvent->pressure : 0.5f :
|
||||
0.0f;
|
||||
event.convertToPointer = mouseEvent->convertToPointer = false;
|
||||
aShell->HandleEvent(aFrame, &event, aDontRetargetEvents, aStatus);
|
||||
aShell->HandleEvent(aFrame, &event, aDontRetargetEvents, aStatus, aTargetContent);
|
||||
} else if (aEvent->mClass == eTouchEventClass) {
|
||||
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
|
||||
// loop over all touches and dispatch pointer events on each touch
|
||||
|
@ -6898,7 +6906,7 @@ DispatchPointerFromMouseOrTouch(PresShell* aShell,
|
|||
event.buttons = WidgetMouseEvent::eLeftButtonFlag;
|
||||
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||
event.convertToPointer = touch->convertToPointer = false;
|
||||
aShell->HandleEvent(aFrame, &event, aDontRetargetEvents, aStatus);
|
||||
aShell->HandleEvent(aFrame, &event, aDontRetargetEvents, aStatus, aTargetContent);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -7165,7 +7173,8 @@ nsresult
|
|||
PresShell::HandleEvent(nsIFrame* aFrame,
|
||||
WidgetGUIEvent* aEvent,
|
||||
bool aDontRetargetEvents,
|
||||
nsEventStatus* aEventStatus)
|
||||
nsEventStatus* aEventStatus,
|
||||
nsIContent** aTargetContent)
|
||||
{
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
// Make touch events, mouse events and hardware key events to be the source
|
||||
|
@ -7181,11 +7190,27 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
|||
AutoSourceEvent taskTracerEvent(type);
|
||||
#endif
|
||||
|
||||
if (sPointerEventEnabled) {
|
||||
DispatchPointerFromMouseOrTouch(this, aFrame, aEvent, aDontRetargetEvents, aEventStatus);
|
||||
}
|
||||
NS_ASSERTION(aFrame, "aFrame should be not null");
|
||||
|
||||
NS_ASSERTION(aFrame, "null frame");
|
||||
if (sPointerEventEnabled) {
|
||||
nsWeakFrame weakFrame(aFrame);
|
||||
nsCOMPtr<nsIContent> targetContent;
|
||||
DispatchPointerFromMouseOrTouch(this, aFrame, aEvent, aDontRetargetEvents,
|
||||
aEventStatus, getter_AddRefs(targetContent));
|
||||
if (!weakFrame.IsAlive()) {
|
||||
if (targetContent) {
|
||||
aFrame = targetContent->GetPrimaryFrame();
|
||||
if (!aFrame) {
|
||||
PushCurrentEventInfo(aFrame, targetContent);
|
||||
nsresult rv = HandleEventInternal(aEvent, aEventStatus);
|
||||
PopCurrentEventInfo();
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mIsDestroying ||
|
||||
(sDisableNonTestMouseEvents && !aEvent->mFlags.mIsSynthesizedForTests &&
|
||||
|
@ -7672,6 +7697,15 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
|||
}
|
||||
}
|
||||
|
||||
// Before HandlePositionedEvent we should save mPointerEventTarget in some cases
|
||||
nsWeakFrame weakFrame;
|
||||
if (sPointerEventEnabled && aTargetContent && ePointerEventClass == aEvent->mClass) {
|
||||
weakFrame = frame;
|
||||
shell->mPointerEventTarget = frame->GetContent();
|
||||
MOZ_ASSERT(!frame->GetContent() || shell->GetDocument() == frame->GetContent()->OwnerDoc());
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
if (shell != this) {
|
||||
// Handle the event in the correct shell.
|
||||
// Prevent deletion until we're done with event handling (bug 336582).
|
||||
|
@ -7680,10 +7714,20 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
|||
// the only correct alternative; if the event was captured then it
|
||||
// must have been captured by us or some ancestor shell and we
|
||||
// now ask the subshell to dispatch it normally.
|
||||
return shell->HandlePositionedEvent(frame, aEvent, aEventStatus);
|
||||
rv = shell->HandlePositionedEvent(frame, aEvent, aEventStatus);
|
||||
} else {
|
||||
rv = HandlePositionedEvent(frame, aEvent, aEventStatus);
|
||||
}
|
||||
|
||||
return HandlePositionedEvent(frame, aEvent, aEventStatus);
|
||||
// After HandlePositionedEvent we should reestablish
|
||||
// content (which still live in tree) in some cases
|
||||
if (sPointerEventEnabled && aTargetContent && ePointerEventClass == aEvent->mClass) {
|
||||
if (!weakFrame.IsAlive()) {
|
||||
shell->mPointerEventTarget.swap(*aTargetContent);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
@ -7920,7 +7964,7 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
|
|||
nsRefPtr<EventStateManager> manager = mPresContext->EventStateManager();
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!NS_EVENT_NEEDS_FRAME(aEvent) || GetCurrentEventFrame()) {
|
||||
if (!NS_EVENT_NEEDS_FRAME(aEvent) || GetCurrentEventFrame() || GetCurrentEventContent()) {
|
||||
bool touchIsNew = false;
|
||||
bool isHandlingUserInput = false;
|
||||
|
||||
|
@ -8033,7 +8077,8 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
|
|||
|
||||
// 1. Give event to event manager for pre event state changes and
|
||||
// generation of synthetic events.
|
||||
rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aStatus);
|
||||
rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame,
|
||||
mCurrentEventContent, aStatus);
|
||||
|
||||
// 2. Give event to the DOM for third party and JS use.
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
@ -8147,9 +8192,9 @@ PresShell::DispatchEventToDOM(WidgetEvent* aEvent,
|
|||
}
|
||||
if (eventTarget) {
|
||||
if (aEvent->mClass == eCompositionEventClass) {
|
||||
IMEStateManager::DispatchCompositionEvent(eventTarget,
|
||||
mPresContext, aEvent->AsCompositionEvent(), aStatus,
|
||||
eventCBPtr);
|
||||
IMEStateManager::DispatchCompositionEvent(eventTarget, mPresContext,
|
||||
aEvent->AsCompositionEvent(),
|
||||
aStatus, eventCBPtr);
|
||||
} else if (aEvent->mClass == eKeyboardEventClass) {
|
||||
HandleKeyboardEvent(eventTarget, *(aEvent->AsKeyboardEvent()),
|
||||
false, aStatus, eventCBPtr);
|
||||
|
|
|
@ -215,7 +215,8 @@ public:
|
|||
virtual nsresult HandleEvent(nsIFrame* aFrame,
|
||||
mozilla::WidgetGUIEvent* aEvent,
|
||||
bool aDontRetargetEvents,
|
||||
nsEventStatus* aEventStatus) override;
|
||||
nsEventStatus* aEventStatus,
|
||||
nsIContent** aTargetContent) override;
|
||||
virtual nsresult HandleDOMEventWithTarget(
|
||||
nsIContent* aTargetContent,
|
||||
mozilla::WidgetEvent* aEvent,
|
||||
|
@ -835,6 +836,11 @@ protected:
|
|||
|
||||
nscoord mLastAnchorScrollPositionY;
|
||||
|
||||
// Information about live content (which still stay in DOM tree).
|
||||
// Used in case we need re-dispatch event after sending pointer event,
|
||||
// when target of pointer event was deleted during executing user handlers.
|
||||
nsCOMPtr<nsIContent> mPointerEventTarget;
|
||||
|
||||
// This is used to protect ourselves from triggering reflow while in the
|
||||
// middle of frame construction and the like... it really shouldn't be
|
||||
// needed, one hopes, but it is for now.
|
||||
|
|
Загрузка…
Ссылка в новой задаче