예제 #1
0
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;
}
예제 #2
0
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);
  }
}
예제 #3
0
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);
  }
}
예제 #4
0
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);
  }
}