backout 387a5f8b5e4f and b45a4dcb88c1

This commit is contained in:
Wes Johnston 2012-10-29 15:45:52 -07:00
Родитель acda0615b5
Коммит a354f49b88
1 изменённых файлов: 117 добавлений и 130 удалений

Просмотреть файл

@ -5652,23 +5652,6 @@ AppendToTouchList(const uint32_t& aKey, nsCOMPtr<nsIDOMTouch>& aData, void *aTou
return PL_DHASH_NEXT;
}
static PLDHashOperator
FindAnyTarget(const uint32_t& aKey, nsCOMPtr<nsIDOMTouch>& aData,
void* aAnyTarget)
{
if (aData) {
nsCOMPtr<nsIDOMEventTarget> target;
aData->GetTarget(getter_AddRefs(target));
if (target) {
nsCOMPtr<nsIContent>* content =
static_cast<nsCOMPtr<nsIContent>*>(aAnyTarget);
*content = do_QueryInterface(target);
return PL_DHASH_STOP;
}
}
return PL_DHASH_NEXT;
}
nsIFrame* GetNearestFrameContainingPresShell(nsIPresShell* aPresShell)
{
nsIView* view = aPresShell->GetViewManager()->GetRootView();
@ -5872,6 +5855,7 @@ PresShell::HandleEvent(nsIFrame *aFrame,
if (!captureRetarget && !isWindowLevelMouseExit) {
nsPoint eventPoint;
if (aEvent->message == NS_TOUCH_START) {
// Add any new touches to the queue
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
// if there is only one touch in this touchstart event, assume that it is
// the start of a new touch session and evict any old touches in the
@ -5883,19 +5867,7 @@ PresShell::HandleEvent(nsIFrame *aFrame,
EvictTouchPoint(touches[i]);
}
}
// 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 (gCaptureTouchList.Count() > 0) {
gCaptureTouchList.Enumerate(&FindAnyTarget, &anyTarget);
} else {
gPreventMouseEvents = false;
}
// Add any new touches to the queue
for (int32_t i = touchEvent->touches.Length(); i; ) {
--i;
for (uint32_t i = 0; i < touchEvent->touches.Length(); ++i) {
nsIDOMTouch *touch = touchEvent->touches[i];
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
touch->mMessage = aEvent->message;
@ -5906,59 +5878,9 @@ PresShell::HandleEvent(nsIFrame *aFrame,
// This event is a new touch. Mark it as a changedTouch and
// add it to the queue.
touch->mChanged = true;
gCaptureTouchList.Put(id, touch);
// find the target for this touch
uint32_t flags = 0;
eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
touch->mRefPoint,
frame);
nsIFrame* target =
FindFrameTargetedByInputEvent(aEvent->eventStructType,
frame,
eventPoint,
flags);
if (target && !anyTarget) {
target->GetContentForEvent(aEvent, getter_AddRefs(anyTarget));
while (anyTarget && !anyTarget->IsElement()) {
anyTarget = anyTarget->GetParent();
}
domtouch->SetTarget(anyTarget);
gCaptureTouchList.Put(id, touch);
} 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->touches array. touchmove events that aren't
// in the captured touch list will be discarded
if (!newTargetFrame) {
touchEvent->touches.RemoveElementAt(i);
} else {
target = newTargetFrame;
nsCOMPtr<nsIContent> targetContent;
target->GetContentForEvent(aEvent, getter_AddRefs(targetContent));
while (targetContent && !targetContent->IsElement()) {
targetContent = targetContent->GetParent();
}
touch->SetTarget(targetContent);
gCaptureTouchList.Put(id, touch);
}
}
if (target) {
frame = target;
}
eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, touch->mRefPoint, frame);
} else {
// This touch is an old touch, we need to ensure that is not
// marked as changed and set its target correctly
@ -6029,6 +5951,47 @@ PresShell::HandleEvent(nsIFrame *aFrame,
PresShell* shell =
static_cast<PresShell*>(frame->PresContext()->PresShell());
switch (aEvent->message) {
case NS_TOUCH_MOVE:
case NS_TOUCH_CANCEL:
case NS_TOUCH_END: {
// Remove the changed touches
// need to make sure we only remove touches that are ending here
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
nsTArray<nsCOMPtr<nsIDOMTouch> > &touches = touchEvent->touches;
for (uint32_t i = 0; i < touches.Length(); ++i) {
nsIDOMTouch *touch = touches[i];
if (!touch) {
break;
}
int32_t id;
touch->GetIdentifier(&id);
nsCOMPtr<nsIDOMTouch> oldTouch;
gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
if (!oldTouch) {
break;
}
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
oldTouch->GetTarget(getter_AddRefs(targetPtr));
nsCOMPtr<nsIContent> content = do_QueryInterface(targetPtr);
if (!content) {
break;
}
nsIFrame* contentFrame = content->GetPrimaryFrame();
if (!contentFrame) {
break;
}
shell = static_cast<PresShell*>(
contentFrame->PresContext()->PresShell());
}
break;
}
}
// Check if we have an active EventStateManager which isn't the
// EventStateManager of the current PresContext.
// If that is the case, and mouse is over some ancestor document,
@ -6391,10 +6354,9 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
case NS_TOUCH_MOVE: {
// Check for touches that changed. Mark them add to queue
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
nsTArray<nsCOMPtr<nsIDOMTouch> >& touches = touchEvent->touches;
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
bool haveChanged = false;
for (int32_t i = touches.Length(); i; ) {
--i;
for (uint32_t i = 0; i < touches.Length(); ++i) {
nsIDOMTouch *touch = touches[i];
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
if (!touch) {
@ -6407,7 +6369,6 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
nsCOMPtr<nsIDOMTouch> oldTouch;
gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
if (!oldTouch) {
touches.RemoveElementAt(i);
continue;
}
if(domtouch->Equals(oldTouch)) {
@ -6417,10 +6378,6 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
oldTouch->GetTarget(getter_AddRefs(targetPtr));
if (!targetPtr) {
touches.RemoveElementAt(i);
continue;
}
domtouch->SetTarget(targetPtr);
gCaptureTouchList.Put(id, touch);
@ -6552,6 +6509,7 @@ PresShell::DispatchTouchEvent(nsEvent *aEvent,
nsPresShellEventCB* aEventCB,
bool aTouchIsNew)
{
nsresult rv = NS_OK;
// calling preventDefault on touchstart or the first touchmove for a
// point prevents mouse events
bool canPrevent = aEvent->message == NS_TOUCH_START ||
@ -6559,56 +6517,85 @@ PresShell::DispatchTouchEvent(nsEvent *aEvent,
bool preventDefault = false;
nsEventStatus tmpStatus = nsEventStatus_eIgnore;
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
// loop over all touches and dispatch events on any that have changed
for (uint32_t i = 0; i < touchEvent->touches.Length(); ++i) {
nsIDOMTouch *touch = touchEvent->touches[i];
if (!touch || !touch->mChanged) {
continue;
}
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
touch->GetTarget(getter_AddRefs(targetPtr));
nsCOMPtr<nsIContent> content = do_QueryInterface(targetPtr);
if (!content) {
continue;
}
nsIContent* capturingContent = GetCapturingContent();
if (capturingContent) {
if (capturingContent->OwnerDoc() != content->OwnerDoc()) {
// Wrong document, don't dispatch anything.
// touch events should fire on all targets
if (aEvent->message != NS_TOUCH_START) {
for (uint32_t i = 0; i < touchEvent->touches.Length(); ++i) {
nsIDOMTouch *touch = touchEvent->touches[i];
if (!touch || !touch->mChanged) {
continue;
}
// copy the event
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
touch->GetTarget(getter_AddRefs(targetPtr));
if (!targetPtr) {
continue;
}
content = capturingContent;
}
// copy the event
nsTouchEvent newEvent(NS_IS_TRUSTED_EVENT(touchEvent) ?
true : false,
touchEvent);
newEvent.target = targetPtr;
nsRefPtr<PresShell> contentPresShell;
if (content->OwnerDoc() == mDocument) {
contentPresShell = static_cast<PresShell*>
(content->OwnerDoc()->GetShell());
nsTouchEvent newEvent(NS_IS_TRUSTED_EVENT(touchEvent) ?
true : false,
touchEvent);
newEvent.target = targetPtr;
// If someone is capturing, all touch events are filtered to their target
nsCOMPtr<nsIContent> content = GetCapturingContent();
// if no one is capturing, set the capturing target
if (!content) {
content = do_QueryInterface(targetPtr);
}
nsRefPtr<PresShell> contentPresShell;
if (content && content->OwnerDoc() == mDocument) {
contentPresShell = static_cast<PresShell*>
(content->OwnerDoc()->GetShell());
if (contentPresShell) {
contentPresShell->PushCurrentEventInfo(
content->GetPrimaryFrame(), content);
}
}
nsPresContext *context = nsContentUtils::GetContextForContent(content);
if (!context) {
context = mPresContext;
}
tmpStatus = nsEventStatus_eIgnore;
nsEventDispatcher::Dispatch(targetPtr, context,
&newEvent, nullptr, &tmpStatus, aEventCB);
if (nsEventStatus_eConsumeNoDefault == tmpStatus) {
preventDefault = true;
}
if (contentPresShell) {
//XXXsmaug huge hack. Pushing possibly capturing content,
// even though event target is something else.
contentPresShell->PushCurrentEventInfo(
content->GetPrimaryFrame(), content);
contentPresShell->PopCurrentEventInfo();
}
}
} else {
// touchevents need to have the target attribute set on each touch
for (uint32_t i = 0; i < touchEvent->touches.Length(); ++i) {
nsIDOMTouch *touch = touchEvent->touches[i];
if (touch->mChanged) {
touch->SetTarget(mCurrentEventContent);
}
}
if (mCurrentEventContent) {
nsEventDispatcher::Dispatch(mCurrentEventContent, mPresContext,
aEvent, nullptr, &tmpStatus, aEventCB);
} else {
nsCOMPtr<nsIContent> targetContent;
rv = mCurrentEventFrame->GetContentForEvent(aEvent,
getter_AddRefs(targetContent));
if (NS_SUCCEEDED(rv) && targetContent) {
nsEventDispatcher::Dispatch(targetContent, mPresContext, aEvent,
nullptr, &tmpStatus, aEventCB);
} else if (mDocument) {
nsEventDispatcher::Dispatch(mDocument, mPresContext, aEvent,
nullptr, &tmpStatus, nullptr);
}
}
nsPresContext *context = nsContentUtils::GetContextForContent(content);
tmpStatus = nsEventStatus_eIgnore;
nsEventDispatcher::Dispatch(targetPtr, context,
&newEvent, nullptr, &tmpStatus, aEventCB);
if (nsEventStatus_eConsumeNoDefault == tmpStatus) {
preventDefault = true;
}
if (contentPresShell) {
contentPresShell->PopCurrentEventInfo();
if (touchEvent->touches.Length() == 1) {
gPreventMouseEvents = false;
}
}