зеркало из https://github.com/mozilla/gecko-dev.git
Bug 790454 - Set touch target in touchstart. r=smaug
This commit is contained in:
Родитель
a53da3dcf1
Коммит
f923e97685
|
@ -5652,6 +5652,23 @@ AppendToTouchList(const uint32_t& aKey, nsCOMPtr<nsIDOMTouch>& aData, void *aTou
|
||||||
return PL_DHASH_NEXT;
|
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)
|
nsIFrame* GetNearestFrameContainingPresShell(nsIPresShell* aPresShell)
|
||||||
{
|
{
|
||||||
nsIView* view = aPresShell->GetViewManager()->GetRootView();
|
nsIView* view = aPresShell->GetViewManager()->GetRootView();
|
||||||
|
@ -5855,7 +5872,6 @@ PresShell::HandleEvent(nsIFrame *aFrame,
|
||||||
if (!captureRetarget && !isWindowLevelMouseExit) {
|
if (!captureRetarget && !isWindowLevelMouseExit) {
|
||||||
nsPoint eventPoint;
|
nsPoint eventPoint;
|
||||||
if (aEvent->message == NS_TOUCH_START) {
|
if (aEvent->message == NS_TOUCH_START) {
|
||||||
// Add any new touches to the queue
|
|
||||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||||
// if there is only one touch in this touchstart event, assume that it is
|
// 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
|
// the start of a new touch session and evict any old touches in the
|
||||||
|
@ -5867,7 +5883,19 @@ PresShell::HandleEvent(nsIFrame *aFrame,
|
||||||
EvictTouchPoint(touches[i]);
|
EvictTouchPoint(touches[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < touchEvent->touches.Length(); ++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;
|
||||||
nsIDOMTouch *touch = touchEvent->touches[i];
|
nsIDOMTouch *touch = touchEvent->touches[i];
|
||||||
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
|
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
|
||||||
touch->mMessage = aEvent->message;
|
touch->mMessage = aEvent->message;
|
||||||
|
@ -5878,9 +5906,58 @@ PresShell::HandleEvent(nsIFrame *aFrame,
|
||||||
// This event is a new touch. Mark it as a changedTouch and
|
// This event is a new touch. Mark it as a changedTouch and
|
||||||
// add it to the queue.
|
// add it to the queue.
|
||||||
touch->mChanged = true;
|
touch->mChanged = true;
|
||||||
gCaptureTouchList.Put(id, touch);
|
|
||||||
|
|
||||||
eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, touch->mRefPoint, frame);
|
// 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;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// This touch is an old touch, we need to ensure that is not
|
// This touch is an old touch, we need to ensure that is not
|
||||||
// marked as changed and set its target correctly
|
// marked as changed and set its target correctly
|
||||||
|
@ -5950,13 +6027,11 @@ PresShell::HandleEvent(nsIFrame *aFrame,
|
||||||
|
|
||||||
PresShell* shell =
|
PresShell* shell =
|
||||||
static_cast<PresShell*>(frame->PresContext()->PresShell());
|
static_cast<PresShell*>(frame->PresContext()->PresShell());
|
||||||
|
|
||||||
switch (aEvent->message) {
|
switch (aEvent->message) {
|
||||||
case NS_TOUCH_MOVE:
|
case NS_TOUCH_MOVE:
|
||||||
case NS_TOUCH_CANCEL:
|
case NS_TOUCH_CANCEL:
|
||||||
case NS_TOUCH_END: {
|
case NS_TOUCH_END: {
|
||||||
// Remove the changed touches
|
// get the correct shell to dispatch to
|
||||||
// need to make sure we only remove touches that are ending here
|
|
||||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||||
nsTArray<nsCOMPtr<nsIDOMTouch> > &touches = touchEvent->touches;
|
nsTArray<nsCOMPtr<nsIDOMTouch> > &touches = touchEvent->touches;
|
||||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||||
|
@ -5987,6 +6062,9 @@ PresShell::HandleEvent(nsIFrame *aFrame,
|
||||||
|
|
||||||
shell = static_cast<PresShell*>(
|
shell = static_cast<PresShell*>(
|
||||||
contentFrame->PresContext()->PresShell());
|
contentFrame->PresContext()->PresShell());
|
||||||
|
if (shell) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6354,9 +6432,10 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||||
case NS_TOUCH_MOVE: {
|
case NS_TOUCH_MOVE: {
|
||||||
// Check for touches that changed. Mark them add to queue
|
// Check for touches that changed. Mark them add to queue
|
||||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||||
nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
|
nsTArray<nsCOMPtr<nsIDOMTouch> >& touches = touchEvent->touches;
|
||||||
bool haveChanged = false;
|
bool haveChanged = false;
|
||||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
for (int32_t i = touches.Length(); i; ) {
|
||||||
|
--i;
|
||||||
nsIDOMTouch *touch = touches[i];
|
nsIDOMTouch *touch = touches[i];
|
||||||
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
|
nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
|
||||||
if (!touch) {
|
if (!touch) {
|
||||||
|
@ -6369,6 +6448,7 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||||
nsCOMPtr<nsIDOMTouch> oldTouch;
|
nsCOMPtr<nsIDOMTouch> oldTouch;
|
||||||
gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
|
gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
|
||||||
if (!oldTouch) {
|
if (!oldTouch) {
|
||||||
|
touches.RemoveElementAt(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(domtouch->Equals(oldTouch)) {
|
if(domtouch->Equals(oldTouch)) {
|
||||||
|
@ -6378,6 +6458,10 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||||
|
|
||||||
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
|
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
|
||||||
oldTouch->GetTarget(getter_AddRefs(targetPtr));
|
oldTouch->GetTarget(getter_AddRefs(targetPtr));
|
||||||
|
if (!targetPtr) {
|
||||||
|
touches.RemoveElementAt(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
domtouch->SetTarget(targetPtr);
|
domtouch->SetTarget(targetPtr);
|
||||||
|
|
||||||
gCaptureTouchList.Put(id, touch);
|
gCaptureTouchList.Put(id, touch);
|
||||||
|
@ -6509,7 +6593,6 @@ PresShell::DispatchTouchEvent(nsEvent *aEvent,
|
||||||
nsPresShellEventCB* aEventCB,
|
nsPresShellEventCB* aEventCB,
|
||||||
bool aTouchIsNew)
|
bool aTouchIsNew)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
|
||||||
// calling preventDefault on touchstart or the first touchmove for a
|
// calling preventDefault on touchstart or the first touchmove for a
|
||||||
// point prevents mouse events
|
// point prevents mouse events
|
||||||
bool canPrevent = aEvent->message == NS_TOUCH_START ||
|
bool canPrevent = aEvent->message == NS_TOUCH_START ||
|
||||||
|
@ -6517,85 +6600,63 @@ PresShell::DispatchTouchEvent(nsEvent *aEvent,
|
||||||
bool preventDefault = false;
|
bool preventDefault = false;
|
||||||
nsEventStatus tmpStatus = nsEventStatus_eIgnore;
|
nsEventStatus tmpStatus = nsEventStatus_eIgnore;
|
||||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||||
// touch events should fire on all targets
|
|
||||||
if (aEvent->message != NS_TOUCH_START) {
|
// loop over all touches and dispatch events on any that have changed
|
||||||
for (uint32_t i = 0; i < touchEvent->touches.Length(); ++i) {
|
for (uint32_t i = 0; i < touchEvent->touches.Length(); ++i) {
|
||||||
nsIDOMTouch *touch = touchEvent->touches[i];
|
nsIDOMTouch *touch = touchEvent->touches[i];
|
||||||
if (!touch || !touch->mChanged) {
|
if (!touch || !touch->mChanged) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// copy the event
|
|
||||||
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
|
nsCOMPtr<nsPIDOMEventTarget> targetPtr;
|
||||||
touch->GetTarget(getter_AddRefs(targetPtr));
|
touch->GetTarget(getter_AddRefs(targetPtr));
|
||||||
if (!targetPtr) {
|
nsCOMPtr<nsIContent> content = do_QueryInterface(targetPtr);
|
||||||
|
if (!content) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIDocument* doc = content->OwnerDoc();
|
||||||
|
nsIContent* capturingContent = GetCapturingContent();
|
||||||
|
if (capturingContent) {
|
||||||
|
if (capturingContent->OwnerDoc() != doc) {
|
||||||
|
// Wrong document, don't dispatch anything.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
content = capturingContent;
|
||||||
|
}
|
||||||
|
// copy the event
|
||||||
|
nsTouchEvent newEvent(NS_IS_TRUSTED_EVENT(touchEvent) ?
|
||||||
|
true : false,
|
||||||
|
touchEvent);
|
||||||
|
newEvent.target = targetPtr;
|
||||||
|
|
||||||
nsTouchEvent newEvent(NS_IS_TRUSTED_EVENT(touchEvent) ?
|
nsRefPtr<PresShell> contentPresShell;
|
||||||
true : false,
|
if (doc == mDocument) {
|
||||||
touchEvent);
|
contentPresShell = static_cast<PresShell*>(doc->GetShell());
|
||||||
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) {
|
if (contentPresShell) {
|
||||||
contentPresShell->PopCurrentEventInfo();
|
//XXXsmaug huge hack. Pushing possibly capturing content,
|
||||||
}
|
// even though event target is something else.
|
||||||
}
|
contentPresShell->PushCurrentEventInfo(
|
||||||
} else {
|
content->GetPrimaryFrame(), content);
|
||||||
// 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) {
|
nsIPresShell *presShell = doc->GetShell();
|
||||||
nsEventDispatcher::Dispatch(mCurrentEventContent, mPresContext,
|
if (!presShell) {
|
||||||
aEvent, nullptr, &tmpStatus, aEventCB);
|
continue;
|
||||||
} 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 = presShell->GetPresContext();
|
||||||
|
|
||||||
|
tmpStatus = nsEventStatus_eIgnore;
|
||||||
|
nsEventDispatcher::Dispatch(targetPtr, context,
|
||||||
|
&newEvent, nullptr, &tmpStatus, aEventCB);
|
||||||
if (nsEventStatus_eConsumeNoDefault == tmpStatus) {
|
if (nsEventStatus_eConsumeNoDefault == tmpStatus) {
|
||||||
preventDefault = true;
|
preventDefault = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (touchEvent->touches.Length() == 1) {
|
if (contentPresShell) {
|
||||||
gPreventMouseEvents = false;
|
contentPresShell->PopCurrentEventInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -530,7 +530,6 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
|
||||||
static_cast<nsMouseEvent*>(aEvent)->button ==
|
static_cast<nsMouseEvent*>(aEvent)->button ==
|
||||||
nsMouseEvent::eMiddleButton) ||
|
nsMouseEvent::eMiddleButton) ||
|
||||||
(aEvent->message == NS_TOUCH_START && GetScrollToClick())) {
|
(aEvent->message == NS_TOUCH_START && GetScrollToClick())) {
|
||||||
|
|
||||||
nsPoint eventPoint;
|
nsPoint eventPoint;
|
||||||
if (!GetEventPoint(aEvent, eventPoint)) {
|
if (!GetEventPoint(aEvent, eventPoint)) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -850,7 +849,6 @@ nsSliderFrame::StartDrag(nsIDOMEvent* aEvent)
|
||||||
#ifdef DEBUG_SLIDER
|
#ifdef DEBUG_SLIDER
|
||||||
printf("Begin dragging\n");
|
printf("Begin dragging\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
|
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
|
||||||
nsGkAtoms::_true, eCaseMatters))
|
nsGkAtoms::_true, eCaseMatters))
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -988,7 +986,6 @@ nsSliderFrame::HandlePress(nsPresContext* aPresContext,
|
||||||
nsEventStatus* aEventStatus)
|
nsEventStatus* aEventStatus)
|
||||||
{
|
{
|
||||||
if (aEvent->message == NS_TOUCH_START && GetScrollToClick()) {
|
if (aEvent->message == NS_TOUCH_START && GetScrollToClick()) {
|
||||||
printf("Bailing for touch\n");
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче