bool APZEventState::SendPendingTouchPreventedResponse(bool aPreventDefault) { if (mPendingTouchPreventedResponse) { APZES_LOG("Sending response %d for pending guid: %s\n", aPreventDefault, Stringify(mPendingTouchPreventedGuid).c_str()); mContentReceivedInputBlockCallback(mPendingTouchPreventedGuid, mPendingTouchPreventedBlockId, aPreventDefault); mPendingTouchPreventedResponse = false; return true; } return false; }
void APZEventState::ProcessLongTap(const nsCOMPtr<nsIPresShell>& aPresShell, const CSSPoint& aPoint, const CSSToLayoutDeviceScale& aScale, Modifiers aModifiers, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) { APZES_LOG("Handling long tap at %s\n", Stringify(aPoint).c_str()); nsCOMPtr<nsIWidget> widget = GetWidget(); if (!widget) { return; } SendPendingTouchPreventedResponse(false); #ifdef XP_WIN // On Windows, we fire the contextmenu events when the user lifts their // finger, in keeping with the platform convention. This happens in the // ProcessLongTapUp function. However, we still fire the eMouseLongTap event // at this time, because things like text selection or dragging may want // to know about it. nsEventStatus status = APZCCallbackHelper::DispatchSynthesizedMouseEvent( eMouseLongTap, /*time*/ 0, aPoint * aScale, aModifiers, /*clickCount*/ 1, widget); bool eventHandled = (status == nsEventStatus_eConsumeNoDefault); #else bool eventHandled = FireContextmenuEvents(aPresShell, aPoint, aScale, aModifiers, widget); #endif mContentReceivedInputBlockCallback(aGuid, aInputBlockId, eventHandled); if (eventHandled) { // Also send a touchcancel to content, so that listeners that might be // waiting for a touchend don't trigger. WidgetTouchEvent cancelTouchEvent(true, eTouchCancel, widget.get()); cancelTouchEvent.mModifiers = aModifiers; auto ldPoint = LayoutDeviceIntPoint::Round(aPoint * aScale); cancelTouchEvent.mTouches.AppendElement(new mozilla::dom::Touch(mLastTouchIdentifier, ldPoint, LayoutDeviceIntPoint(), 0, 0)); APZCCallbackHelper::DispatchWidgetEvent(cancelTouchEvent); } }
void APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId, nsEventStatus aApzResponse, nsEventStatus aContentResponse) { if (aEvent.mMessage == eTouchStart && aEvent.mTouches.Length() > 0) { mActiveElementManager->SetTargetElement(aEvent.mTouches[0]->GetTarget()); mLastTouchIdentifier = aEvent.mTouches[0]->Identifier(); } bool isTouchPrevented = aContentResponse == nsEventStatus_eConsumeNoDefault; bool sentContentResponse = false; APZES_LOG("Handling event type %d\n", aEvent.mMessage); switch (aEvent.mMessage) { case eTouchStart: { mTouchEndCancelled = false; sentContentResponse = SendPendingTouchPreventedResponse(false); // sentContentResponse can be true here if we get two TOUCH_STARTs in a row // and just responded to the first one. // We're about to send a response back to APZ, but we should only do it // for events that went through APZ (which should be all of them). MOZ_ASSERT(aEvent.mFlags.mHandledByAPZ); if (isTouchPrevented) { mContentReceivedInputBlockCallback(aGuid, aInputBlockId, isTouchPrevented); sentContentResponse = true; } else { APZES_LOG("Event not prevented; pending response for %" PRIu64 " %s\n", aInputBlockId, Stringify(aGuid).c_str()); mPendingTouchPreventedResponse = true; mPendingTouchPreventedGuid = aGuid; mPendingTouchPreventedBlockId = aInputBlockId; } break; } case eTouchEnd: if (isTouchPrevented) { mTouchEndCancelled = true; mEndTouchIsClick = false; } MOZ_FALLTHROUGH; case eTouchCancel: mActiveElementManager->HandleTouchEndEvent(mEndTouchIsClick); MOZ_FALLTHROUGH; case eTouchMove: { if (mPendingTouchPreventedResponse) { MOZ_ASSERT(aGuid == mPendingTouchPreventedGuid); } sentContentResponse = SendPendingTouchPreventedResponse(isTouchPrevented); break; } default: NS_WARNING("Unknown touch event type"); } if (sentContentResponse && aApzResponse == nsEventStatus_eConsumeDoDefault && gfxPrefs::PointerEventsEnabled()) { WidgetTouchEvent cancelEvent(aEvent); cancelEvent.mMessage = eTouchCancel; cancelEvent.mFlags.mCancelable = false; // mMessage != eTouchCancel; for (uint32_t i = 0; i < cancelEvent.mTouches.Length(); ++i) { if (mozilla::dom::Touch* touch = cancelEvent.mTouches[i]) { touch->convertToPointer = true; } } nsEventStatus status; cancelEvent.mWidget->DispatchEvent(&cancelEvent, status); } }
void APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId, nsEventStatus aApzResponse, nsEventStatus aContentResponse) { if (aEvent.mMessage == eTouchStart && aEvent.mTouches.Length() > 0) { mActiveElementManager->SetTargetElement(aEvent.mTouches[0]->GetTarget()); } bool isTouchPrevented = aContentResponse == nsEventStatus_eConsumeNoDefault; bool sentContentResponse = false; APZES_LOG("Handling event type %d\n", aEvent.mMessage); switch (aEvent.mMessage) { case eTouchStart: { mTouchEndCancelled = false; sentContentResponse = SendPendingTouchPreventedResponse(false); // sentContentResponse can be true here if we get two TOUCH_STARTs in a row // and just responded to the first one. if (!aEvent.mFlags.mHandledByAPZ) { // This condition being true means this touchstart is synthetic and is // coming from TabParent.injectTouchEvent. // Since APZ doesn't know about it we don't want to send a response for // this block; we want to just skip over it from the point of view of // prevent-default notifications. APZES_LOG("Got a synthetic touch-start!\n"); break; } if (isTouchPrevented) { mContentReceivedInputBlockCallback(aGuid, aInputBlockId, isTouchPrevented); sentContentResponse = true; } else { APZES_LOG("Event not prevented; pending response for %" PRIu64 " %s\n", aInputBlockId, Stringify(aGuid).c_str()); mPendingTouchPreventedResponse = true; mPendingTouchPreventedGuid = aGuid; mPendingTouchPreventedBlockId = aInputBlockId; } break; } case eTouchEnd: if (isTouchPrevented) { mTouchEndCancelled = true; mEndTouchIsClick = false; } MOZ_FALLTHROUGH; case eTouchCancel: mActiveElementManager->HandleTouchEndEvent(mEndTouchIsClick); MOZ_FALLTHROUGH; case eTouchMove: { if (mPendingTouchPreventedResponse) { MOZ_ASSERT(aGuid == mPendingTouchPreventedGuid); } sentContentResponse = SendPendingTouchPreventedResponse(isTouchPrevented); break; } default: NS_WARNING("Unknown touch event type"); } if (sentContentResponse && aApzResponse == nsEventStatus_eConsumeDoDefault && gfxPrefs::PointerEventsEnabled()) { WidgetTouchEvent cancelEvent(aEvent); cancelEvent.mMessage = eTouchCancel; cancelEvent.mFlags.mCancelable = false; // mMessage != eTouchCancel; for (uint32_t i = 0; i < cancelEvent.mTouches.Length(); ++i) { if (mozilla::dom::Touch* touch = cancelEvent.mTouches[i]) { touch->convertToPointer = true; } } nsEventStatus status; cancelEvent.widget->DispatchEvent(&cancelEvent, status); } }