Bug 1420589 Part1: Separate the logic of finding the event target for touch events into a function. r=smaug.

MozReview-Commit-ID: 5IWpVBdiQ3o
This commit is contained in:
Stone Shih
2017-11-22 11:36:35 +08:00
parent 4d0ebca380
commit 0ce97358e9
3 changed files with 113 additions and 99 deletions

View File

@@ -7087,11 +7087,6 @@ PresShell::HandleEvent(nsIFrame* aFrame,
}
}
// all touch events except for touchstart use a captured target
if (aEvent->mClass == eTouchEventClass && aEvent->mMessage != eTouchStart) {
captureRetarget = true;
}
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
bool isWindowLevelMouseExit = (aEvent->mMessage == eMouseExitFromWidget) &&
(mouseEvent && mouseEvent->mExitFrom == WidgetMouseEvent::eTopLevel);
@@ -7102,103 +7097,22 @@ PresShell::HandleEvent(nsIFrame* aFrame,
// with a window-level mouse exit event since we want to start sending
// mouse out events at the root EventStateManager.
if (!captureRetarget && !isWindowLevelMouseExit) {
nsPoint eventPoint;
uint32_t flags = 0;
if (aEvent->mMessage == eTouchStart) {
if (gfxPrefs::APZAllowZooming()) {
// Setting this flag will skip the scrollbars on the root frame from
// participating in hit-testing, and we only want that to happen on
// zoomable platforms (for now).
if (aEvent->mClass == eTouchEventClass) {
frame = TouchManager::SetupTarget(aEvent->AsTouchEvent(), frame);
} else {
uint32_t flags = 0;
nsPoint eventPoint =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
if (mouseEvent && mouseEvent->mClass == eMouseEventClass &&
mouseEvent->mIgnoreRootScrollFrame) {
flags |= INPUT_IGNORE_ROOT_SCROLL_FRAME;
}
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
// if this is a continuing session, ensure that all these events are
// in the same document by taking the target of the events already in
// the capture list
nsCOMPtr<nsIContent> anyTarget;
if (touchEvent->mTouches.Length() > 1) {
anyTarget = TouchManager::GetAnyCapturedTouchTarget();
nsIFrame* target =
FindFrameTargetedByInputEvent(aEvent, frame, eventPoint, flags);
if (target) {
frame = target;
}
// When handling pointerstart with multiple touch points, frame is
// overwritten. Keep the original root frame for hit test.
nsIFrame* rootFrame = frame;
for (int32_t i = touchEvent->mTouches.Length(); i; ) {
--i;
dom::Touch* touch = touchEvent->mTouches[i];
int32_t id = touch->Identifier();
if (!TouchManager::HasCapturedTouch(id)) {
// find the target for this touch
eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
touch->mRefPoint,
rootFrame);
nsIFrame* target = FindFrameTargetedByInputEvent(aEvent,
rootFrame,
eventPoint,
flags);
if (target && !anyTarget) {
target->GetContentForEvent(aEvent, getter_AddRefs(anyTarget));
while (anyTarget && !anyTarget->IsElement()) {
anyTarget = anyTarget->GetParent();
}
touch->SetTarget(anyTarget);
} else {
nsIFrame* newTargetFrame = nullptr;
for (nsIFrame* f = target; f;
f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
if (f->PresContext()->Document() == anyTarget->OwnerDoc()) {
newTargetFrame = f;
break;
}
// We must be in a subdocument so jump directly to the root frame.
// GetParentOrPlaceholderForCrossDoc gets called immediately to
// jump up to the containing document.
f = f->PresContext()->GetPresShell()->GetRootFrame();
}
// if we couldn't find a target frame in the same document as
// anyTarget, remove the touch from the capture touch list, as
// well as the event->mTouches array. touchmove events that aren't
// in the captured touch list will be discarded
if (!newTargetFrame) {
touchEvent->mTouches.RemoveElementAt(i);
} else {
target = newTargetFrame;
nsCOMPtr<nsIContent> targetContent;
target->GetContentForEvent(aEvent, getter_AddRefs(targetContent));
while (targetContent && !targetContent->IsElement()) {
targetContent = targetContent->GetParent();
}
touch->SetTarget(targetContent);
}
}
if (target) {
frame = target;
}
} else {
// This touch is an old touch, we need to ensure that is not
// marked as changed and set its target correctly
touch->mChanged = false;
int32_t id = touch->Identifier();
RefPtr<dom::Touch> oldTouch = TouchManager::GetCapturedTouch(id);
if (oldTouch) {
touch->SetTarget(oldTouch->mTarget);
}
}
}
} else {
eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
}
if (mouseEvent && mouseEvent->mClass == eMouseEventClass &&
mouseEvent->mIgnoreRootScrollFrame) {
flags |= INPUT_IGNORE_ROOT_SCROLL_FRAME;
}
nsIFrame* target =
FindFrameTargetedByInputEvent(aEvent, frame, eventPoint, flags);
if (target) {
frame = target;
}
}