void EventInputQueue::BlockUntilKeyUpHander::blockingTimeOut_timer_callback(OSObject* owner, IOTimerEventSource* sender) { endBlocking(); setIgnoreToAllPressingEvents(); setTimer(); }
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; }