예제 #1
0
 void
 EventInputQueue::BlockUntilKeyUpHander::blockingTimeOut_timer_callback(OSObject* owner, IOTimerEventSource* sender)
 {
   endBlocking();
   setIgnoreToAllPressingEvents();
   setTimer();
 }
예제 #2
0
bool EventInputQueue::BlockUntilKeyUpHander::doBlockUntilKeyUp(void) {
  Item* front = static_cast<Item*>(queue_.safe_front());
  if (!front) return true;

  // Ignore events enqueued from blockedQueue_.
  if (front->enqueuedFrom == Item::ENQUEUED_FROM_BLOCKEDQUEUE) return true;

  // Ignore events that are not down/up events.
  // (For example, mouse cursor move events.)
  bool iskeydown = false;
  if (!(front->getParamsBase()).iskeydown(iskeydown)) return true;

  // ----------------------------------------
  // Modify pressingEvents_.
  //

  // Remove existing events.
  {
    PressingEvent* p = static_cast<PressingEvent*>(pressingEvents_.safe_front());
    for (;;) {
      if (!p) break;

      if ((p->getFromEvent()).isTargetDownEvent(front->getParamsBase()) ||
          (p->getFromEvent()).isTargetUpEvent(front->getParamsBase())) {
        p = static_cast<PressingEvent*>(pressingEvents_.erase_and_delete(p));
      } else {
        p = static_cast<PressingEvent*>(p->getnext());
      }
    }
  }

  // Add to list.
  if (iskeydown) {
    pressingEvents_.push_back(new PressingEvent(front->getParamsBase()));
  }

  // ----------------------------------------
  // Test whether pressingEvents_ are a target event of BlockUntilKeyUp.
  //

  for (PressingEvent* p = static_cast<PressingEvent*>(pressingEvents_.safe_front()); p; p = static_cast<PressingEvent*>(p->getnext())) {
    if (p->ignore()) continue;

    if (RemapClassManager::isTargetEventForBlockUntilKeyUp(p->getParamsBase())) {
      goto needToBlock;
    }
  }

  // If current event is target event, we need to block it.
  if (RemapClassManager::isTargetEventForBlockUntilKeyUp(front->getParamsBase())) {
    goto needToBlock;
  }

  endBlocking();
  return true;

needToBlock:
  // Set timeout at first.
  {
    int timeout = Config::get_essential_config(BRIDGE_ESSENTIAL_CONFIG_INDEX_parameter_blockuntilkeyup_timeout);
    blockingTimeOut_timer_.setTimeoutMS(timeout);
  }

  // When <autogen>__BlockUntilKeyUp__ KeyCode::SPACE</autogen> is enabled:
  //
  // Case 1:
  //   * Space down
  //   * T down
  //   * T up         <- up event and event != Space
  //
  //   => Enqueue "Space down, T down, T up".
  //
  //   Note:
  //     If there is an orphan key up event,
  //     user is typing fast and we should change key events order in Case 2.
  //     So, we keep blocking.
  //
  //       * M down
  //       * Space down  (start blocking)
  //       * M up        (orphan key up event)
  //       * T down
  //       * T up
  //
  // Case 2:
  //   * Space down
  //   * T down
  //   * Space up     <- up event and event == Space
  //
  //   => Move "Space up" after "Space down".
  //      Then, Enqueue "Space down, Space up, T down".
  //

  if (!iskeydown && RemapClassManager::isTargetEventForBlockUntilKeyUp(front->getParamsBase())) {
    // Case2

    // Do not call setIgnoreToAllPressingEvents here.
    //
    // We do not need to call that here because front->p_ is already removed from pressingEvents_.
    // And if multiple __BlockUntilKeyUp__ are enabled,
    // setIgnoreToAllPressingEvents breaks other __BlockUntilKeyUp__.

    // Move up event after down event.
    FromEvent fromEvent(front->getParamsBase());
    for (Item* p = static_cast<Item*>(blockedQueue_.safe_back()); p; p = static_cast<Item*>(p->getprev())) {
      if (fromEvent.isTargetDownEvent(p->getParamsBase())) {
        if (p->getnext()) {
          blockedQueue_.insert(p->getnext(), new Item(*front));
        } else {
          blockedQueue_.push_back(new Item(*front));
        }
        goto endBlocking;
      }
    }
    // corresponded event is not found.
    blockedQueue_.push_front(new Item(*front));
    goto endBlocking;

  } else if (!iskeydown &&
             !isOrphanKeyUpEventExistsInBlockedQueue() &&
             isTargetDownEventInBlockedQueue(*front)) {
    // Case 1

    setIgnoreToAllPressingEvents();

    blockedQueue_.push_back(new Item(*front));
    goto endBlocking;
  }

  blockedQueue_.push_back(new Item(*front));
  queue_.pop_front();
  // Do not call doFire.
  return false;

endBlocking:
  queue_.pop_front();
  endBlocking();
  return true;
}