void
APZCCallbackHelper::SendSetTargetAPZCNotification(nsIWidget* aWidget,
                                                  nsIDocument* aDocument,
                                                  const WidgetGUIEvent& aEvent,
                                                  const ScrollableLayerGuid& aGuid,
                                                  uint64_t aInputBlockId)
{
  if (!aWidget || !aDocument) {
    return;
  }
  if (aInputBlockId == sLastTargetAPZCNotificationInputBlock) {
    // We have already confirmed the target APZC for a previous event of this
    // input block. If we activated a scroll frame for this input block,
    // sending another target APZC confirmation would be harmful, as it might
    // race the original confirmation (which needs to go through a layers
    // transaction).
    APZCCH_LOG("Not resending target APZC confirmation for input block %" PRIu64 "\n", aInputBlockId);
    return;
  }
  sLastTargetAPZCNotificationInputBlock = aInputBlockId;
  if (nsIPresShell* shell = aDocument->GetShell()) {
    if (nsIFrame* rootFrame = shell->GetRootFrame()) {
      bool waitForRefresh = false;
      nsTArray<ScrollableLayerGuid> targets;

      if (const WidgetTouchEvent* touchEvent = aEvent.AsTouchEvent()) {
        for (size_t i = 0; i < touchEvent->touches.Length(); i++) {
          waitForRefresh |= PrepareForSetTargetAPZCNotification(aWidget, aGuid,
              rootFrame, touchEvent->touches[i]->mRefPoint, &targets);
        }
      } else if (const WidgetWheelEvent* wheelEvent = aEvent.AsWheelEvent()) {
        waitForRefresh = PrepareForSetTargetAPZCNotification(aWidget, aGuid,
            rootFrame, wheelEvent->refPoint, &targets);
      }
      // TODO: Do other types of events need to be handled?

      if (!targets.IsEmpty()) {
        SendSetTargetAPZCNotificationHelper(
          aWidget,
          shell,
          aInputBlockId,
          targets,
          waitForRefresh);
      }
    }
  }
}
nsresult
TextEventDispatcher::DispatchEvent(nsIWidget* aWidget,
                                   WidgetGUIEvent& aEvent,
                                   nsEventStatus& aStatus)
{
  nsRefPtr<TextEventDispatcher> kungFuDeathGrip(this);
  nsCOMPtr<nsIWidget> widget(aWidget);
  mDispatchingEvent++;

  nsresult rv = NS_OK;
  if (aEvent.AsInputEvent() &&
      (!aEvent.mFlags.mIsSynthesizedForTests || gfxPrefs::TestEventsAsyncEnabled()))
  {
    aStatus = widget->DispatchInputEvent(aEvent.AsInputEvent());
  } else {
    rv = widget->DispatchEvent(&aEvent, aStatus);
  }

  mDispatchingEvent--;
  return rv;
}
nsresult
TextEventDispatcher::DispatchEvent(nsIWidget* aWidget,
                                   WidgetGUIEvent& aEvent,
                                   nsEventStatus& aStatus)
{
  MOZ_ASSERT(!aEvent.AsInputEvent(), "Use DispatchInputEvent()");

  RefPtr<TextEventDispatcher> kungFuDeathGrip(this);
  nsCOMPtr<nsIWidget> widget(aWidget);
  mDispatchingEvent++;
  nsresult rv = widget->DispatchEvent(&aEvent, aStatus);
  mDispatchingEvent--;
  return rv;
}
void
APZCCallbackHelper::SendSetTargetAPZCNotification(nsIWidget* aWidget,
                                                  nsIDocument* aDocument,
                                                  const WidgetGUIEvent& aEvent,
                                                  const ScrollableLayerGuid& aGuid,
                                                  uint64_t aInputBlockId)
{
  if (!aWidget || !aDocument) {
    return;
  }
  if (nsIPresShell* shell = aDocument->GetShell()) {
    if (nsIFrame* rootFrame = shell->GetRootFrame()) {
      bool waitForRefresh = false;
      nsTArray<ScrollableLayerGuid> targets;

      if (const WidgetTouchEvent* touchEvent = aEvent.AsTouchEvent()) {
        for (size_t i = 0; i < touchEvent->touches.Length(); i++) {
          waitForRefresh |= PrepareForSetTargetAPZCNotification(aWidget, aGuid,
              rootFrame, touchEvent->touches[i]->mRefPoint, &targets);
        }
      } else if (const WidgetWheelEvent* wheelEvent = aEvent.AsWheelEvent()) {
        waitForRefresh = PrepareForSetTargetAPZCNotification(aWidget, aGuid,
            rootFrame, wheelEvent->refPoint, &targets);
      }
      // TODO: Do other types of events need to be handled?

      if (!targets.IsEmpty()) {
        SendSetTargetAPZCNotificationHelper(
          aWidget,
          shell,
          aInputBlockId,
          targets,
          waitForRefresh);
      }
    }
  }
}
void
TextEventDispatcher::InitEvent(WidgetGUIEvent& aEvent) const
{
  aEvent.time = PR_IntervalNow();
  aEvent.refPoint = LayoutDeviceIntPoint(0, 0);
  aEvent.mFlags.mIsSynthesizedForTests = mForTests;
  if (aEvent.mClass != eCompositionEventClass) {
    return;
  }
  // Currently, we should set special native IME context when composition
  // events are dispatched from PuppetWidget since PuppetWidget may have not
  // known actual native IME context yet and it caches native IME context
  // when it dispatches every WidgetCompositionEvent.
  if (XRE_IsContentProcess()) {
    aEvent.AsCompositionEvent()->
      mNativeIMEContext.InitWithRawNativeIMEContext(mWidget);
  }
}