bool
    PointingRelativeToScroll::remap(RemapPointingParams_relative& remapParams)
    {
      bool active = fromkeychecker_.isactive();

      if (remapParams.isremapped) return false;
      if (fromButton_ == PointingButton::NONE) {
        if (! FlagStatus::makeFlags().isOn(fromFlags_)) return false;
      } else {
        if (! fromkeychecker_.isFromPointingButton(remapParams.params, fromButton_, fromFlags_) && ! active) return false;
      }
      remapParams.isremapped = true;

      if (fromButton_ == PointingButton::NONE) {
        goto doremap;
      }

      // first time
      if (! active) {
        // if the source buttons contains left button, we cancel left click for iPhoto, or some applications.
        // iPhoto store the scroll events when left button is pressed, and restore events after left button is released.
        // PointingRelativeToScroll doesn't aim it, we release the left button and do normal scroll event.
        ButtonStatus::decrease(fromButton_);
        EventOutputQueue::FireRelativePointer::fire();
        ButtonStatus::increase(fromButton_);

        absolute_distance_ = 0;
        begin_ic_.begin();
        chained_ic_.begin();
        chained_delta1_ = 0;
        chained_delta2_ = 0;

        goto doremap;
      }

      // last time
      if (! fromkeychecker_.isactive()) {
        cancelScroll();

        const uint32_t DISTANCE_THRESHOLD = 5;
        const uint32_t TIME_THRESHOLD = 300;
        if (absolute_distance_ <= DISTANCE_THRESHOLD && begin_ic_.getmillisec() < TIME_THRESHOLD) {
          // Fire by a click event.
          ButtonStatus::increase(fromButton_);
          EventOutputQueue::FireRelativePointer::fire();
          ButtonStatus::decrease(fromButton_);
          EventOutputQueue::FireRelativePointer::fire();
        }
        return true;
      }

    doremap:
      // We need to call EventWatcher::on here.
      // See the comments in EventInputQueue::fire_timer_callback.
      EventWatcher::on();
      toscroll(remapParams);

      return true;
    }
    bool
    PointingRelativeToScroll::remap(RemapParams& remapParams)
    {
      // ------------------------------------------------------------
      // PointingRelativeToScroll grabs all pointing movement events.
      // Therefore, if user write inappropriate <autogen> (empty flags and empty buttons),
      // user cannot control pointing device at all.
      //
      // For example:
      //   <autogen>__PointingRelativeToScroll__ PointingButton::LEFT | PointingButton::RIGHT</autogen>
      //
      // (Buttons(LEFT | RIGHT) will be ignored. So, this autogen is interpreted as
      // <autogen>__PointingRelativeToScroll__</autogen>.)
      //
      // Skip on error in order to avoid this situation.
      if (fromEvent_.getType() == FromEvent::Type::NONE &&
          fromFlags_ == Flags(0)) {
        IOLOG_WARN("Ignore __PointingRelativeToScroll__ with no option. "
                   "Please use \"__PointingRelativeToScroll__ PointingButton::NONE\".\n");
        return false;
      }

      // ------------------------------------------------------------
      if (remapParams.isremapped) return false;

      bool useFromEvent = true;
      if (fromEvent_.getType() == FromEvent::Type::NONE) {
        useFromEvent = false;
      }
      if (fromEvent_.getType() == FromEvent::Type::POINTING_BUTTON &&
          fromEvent_.getPointingButton() == PointingButton::NONE) {
        useFromEvent = false;
      }

      if (! useFromEvent) {
        if (! FlagStatus::makeFlags().isOn(fromFlags_)) return false;
        goto doremap;

      } else {
        // FromEvent == KeyCode or ConsumerKeyCode or PointingButton.

        bool pressingStateChanged = fromEvent_.changePressingState(remapParams.paramsUnion,
                                                                   FlagStatus::makeFlags(),
                                                                   fromFlags_);
        if (pressingStateChanged) {
          if (fromEvent_.isPressing()) {
            // down event
            FlagStatus::decrease(fromEvent_.getModifierFlag());
            ButtonStatus::decrease(fromEvent_.getPointingButton());

            absolute_distance_ = 0;
            begin_ic_.begin();
            chained_ic_.begin();
            chained_delta1_ = 0;
            chained_delta2_ = 0;

          } else {
            // up event
            FlagStatus::increase(fromEvent_.getModifierFlag());
            ButtonStatus::increase(fromEvent_.getPointingButton());

            cancelScroll();

            const uint32_t DISTANCE_THRESHOLD = 5;
            const uint32_t TIME_THRESHOLD = 300;
            if (absolute_distance_ <= DISTANCE_THRESHOLD && begin_ic_.getmillisec() < TIME_THRESHOLD) {
              // Fire by a click event.
              if (isToKeysDefined_) {
                keytokey_.call_remap_with_VK_PSEUDO_KEY(EventType::DOWN);
                keytokey_.call_remap_with_VK_PSEUDO_KEY(EventType::UP);

              } else {
                toEvent_.fire_downup(FlagStatus::makeFlags());
              }
            }
          }

          // ignore this event.
          goto returntrue;

        } else {
          if (! fromEvent_.isPressing()) {
            return false;
          }
        }
      }

    doremap:
      // change only cursor move events.
      {
        Params_RelativePointerEventCallback* params = remapParams.paramsUnion.get_Params_RelativePointerEventCallback();
        if (! params) return false;
        if (params->ex_button != PointingButton::NONE) return false;
      }

      // We need to call EventWatcher::on here.
      // See the comments in EventInputQueue::fire_timer_callback.
      EventWatcher::on();
      toscroll(remapParams);

    returntrue:
      remapParams.isremapped = true;
      return true;
    }