void SimultaneousKeyPresses::push_remapped(bool isKeyDown, const DeviceIdentifier& deviceIdentifier) { EventType eventType = isKeyDown ? EventType::DOWN : EventType::UP; KeyCode key = virtualkey_; if (isToRaw_) { key = toKey_raw_; } if (key == KeyCode::VK_NONE) return; Flags flags(0); if (isKeyDown) { flags.add(key.getModifierFlag()); flags.stripNONE(); } // ---------------------------------------- Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(eventType, flags, key, CommonData::getcurrent_keyboardType(), false)); if (! ptr) return; Params_KeyboardEventCallBack& params = *ptr; bool retainFlagStatusTemporaryCount = false; bool push_back = false; EventInputQueue::enqueue_(params, retainFlagStatusTemporaryCount, deviceIdentifier, push_back); }
void KeypadWidget::changeKeyState(KeyCode keycode, bool press, bool toggleHold) { if (Key *key = m_keys[keycode.row()][keycode.col()]) { bool wasSelected = key->isSelected(); key->setPressed(press); if (toggleHold) { key->toggleHeld(); } bool selected = key->isSelected(); if (selected != wasSelected) { update(m_transform.mapRect(key->keyGeometry())); keypad_key_event(keycode.row(), keycode.col(), selected); } } }
// ------------------------------------------------------------ bool EventType::isKeyDownOrModifierDown(KeyCode key, Flags flags) const { if (*this == EventType::DOWN) return true; if (*this == EventType::MODIFY) { return flags.isOn(key.getModifierFlag()); } return false; }
void PressDownKeys::add(KeyCode key, KeyboardType keyboardType) { if (key == KeyCode::VK_NONE) return; list_.push_back(new Item(key, keyboardType)); IOLOG_DEVEL("PressDownKeys::add key:%d, keyboardType:%d\n", key.get(), keyboardType.get()); }
void SimultaneousKeyPresses::push_remapped(bool isKeyDown, const DeviceIdentifier& deviceIdentifier, const ListHookedDevice::WeakPointer_Item& device) { EventType eventType = isKeyDown ? EventType::DOWN : EventType::UP; KeyCode key = virtualkey_; if (isToRaw_) { key = toKey_raw_; } if (key == KeyCode::VK_NONE) return; Flags flags(0); if (isKeyDown) { flags.add(key.getModifierFlag()); } // ---------------------------------------- Params_KeyboardEventCallBack params(eventType, flags, key, CommonData::getcurrent_keyboardType(), false); bool retainFlagStatusTemporaryCount = false; bool push_back = false; bool isSimultaneousKeyPressesTarget = false; EventInputQueue::enqueue_(params, retainFlagStatusTemporaryCount, deviceIdentifier, device, push_back, isSimultaneousKeyPressesTarget); }
void BerkeliumWidget::onKeyButtonReleased(KeyCode _key) { if (mWindow != nullptr) { InputManager& manager = InputManager::getInstance(); int mod = 0; if (manager.isControlPressed()) mod |= Berkelium::CONTROL_MOD; if (manager.isShiftPressed()) mod |= Berkelium::SHIFT_MOD; mWindow->keyEvent(false, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0); } Base::onKeyButtonReleased(_key); }
void PressDownKeys::remove(KeyCode key, KeyboardType keyboardType) { Item* p = static_cast<Item*>(list_.safe_front()); for (;;) { if (!p) break; if (p->key == key && p->keyboardType == keyboardType) { p = static_cast<Item*>(list_.erase_and_delete(p)); } else { p = static_cast<Item*>(p->getnext()); } } IOLOG_DEVEL("PressDownKeys::remove key:%d, keyboardType:%d\n", key.get(), keyboardType.get()); }
void KeyboardRepeat::set(EventType eventType, Flags flags, KeyCode key, KeyboardType keyboardType, int delayUntilRepeat, int keyRepeat) { if (! queue_) return; if (key == KeyCode::VK_NONE) return; if (eventType == EventType::MODIFY) { goto cancel; } else if (eventType == EventType::UP) { // The repetition of plural keys is controlled by manual operation. // So, we ignore it. if (queue_->size() != 1) return; // We stop key repeat only when the repeating key is up. KeyboardRepeat::Item* p = static_cast<KeyboardRepeat::Item*>(queue_->front()); if (p && (p->params).type == ParamsUnion::KEYBOARD) { Params_KeyboardEventCallBack* params = (p->params).params.params_KeyboardEventCallBack; if (params && key == params->key) { goto cancel; } } } else if (eventType == EventType::DOWN) { cancel(); primitive_add(eventType, flags, key, keyboardType, Item::TYPE_NORMAL); primitive_start(delayUntilRepeat, keyRepeat); IOLOG_DEVEL("KeyboardRepeat::set key:%d flags:0x%x\n", key.get(), flags.get()); } else { goto cancel; } return; cancel: cancel(); }
void EventOutputQueue::FireKey::fire_downup(Flags flags, KeyCode key, KeyboardType keyboardType) { ModifierFlag f = key.getModifierFlag(); if (f != ModifierFlag::ZERO) { FlagStatus::ScopedTemporaryFlagsChanger stfc(FlagStatus::globalFlagStatus(), flags); // We operate FlagStatus for the case "key == KeyCode::CAPSLOCK". FlagStatus::globalFlagStatus().increase(f); { Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(EventType::MODIFY, FlagStatus::globalFlagStatus().makeFlags(), key, keyboardType, false)); if (! ptr) return; FireKey::fire(*ptr); } FlagStatus::globalFlagStatus().decrease(f); { Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(EventType::MODIFY, FlagStatus::globalFlagStatus().makeFlags(), key, keyboardType, false)); if (! ptr) return; FireKey::fire(*ptr); } } else { { Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(EventType::DOWN, flags, key, keyboardType, false)); if (! ptr) return; FireKey::fire(*ptr); } { Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(EventType::UP, flags, key, keyboardType, false)); if (! ptr) return; FireKey::fire(*ptr); } } }
void KeyboardRepeat::set(EventType eventType, Flags flags, KeyCode key, KeyboardType keyboardType, int delayUntilRepeat, int keyRepeat) { if (key == KeyCode::VK_NONE) return; if (eventType == EventType::MODIFY) { goto cancel; } else if (eventType == EventType::UP) { // The repetition of multiple keys is controlled by manual operation. // So, we ignore it. if (queue_.size() != 1) return; // We stop key repeat only when the repeating key is up. KeyboardRepeat::Item* p = static_cast<KeyboardRepeat::Item*>(queue_.safe_front()); if (p) { auto params = (p->getParamsBase()).get_Params_KeyboardEventCallBack(); if (params && key == params->key) { goto cancel; } } } else if (eventType == EventType::DOWN) { cancel(); primitive_add(eventType, flags, key, keyboardType); primitive_start(delayUntilRepeat, keyRepeat); IOLOG_DEVEL("KeyboardRepeat::set key:%d flags:0x%x\n", key.get(), flags.get()); } else { goto cancel; } return; cancel: cancel(); }
void BerkeliumWidget::onKeyButtonPressed(KeyCode _key, Char _char) { if (mWindow != nullptr) { InputManager& manager = InputManager::getInstance(); int mod = 0; if (manager.isControlPressed()) mod |= Berkelium::CONTROL_MOD; if (manager.isShiftPressed()) mod |= Berkelium::SHIFT_MOD; mWindow->keyEvent(true, mod, input::ScanCodeToVirtualKey(_key.toValue()), 0); if (_char != 0) { wchar_t text = (wchar_t)_char; mWindow->textEvent(&text, 1); } } Base::onKeyButtonPressed(_key, _char); }
// ---------------------------------------- static void log(bool isCaught, EventType eventType, Flags flags, KeyCode key, KeyboardType keyboardType, bool repeat) { IOLOG_DEBUG("KeyboardEventCallback [%7s]: eventType %2d, flags 0x%08x, key 0x%04x, kbdType %3d, repeat = %d\n", isCaught ? "caught" : "sending", eventType.get(), flags.get(), key.get(), keyboardType.get(), repeat); }
void add(KeyToKeyType::Value type, KeyCode newval) { add(type, BRIDGE_DATATYPE_KEYCODE, newval.get()); }
bool KeyToKey::remap(RemapParams& remapParams) { if (remapParams.isremapped) return false; if (! fromkeychecker_.isFromKey(remapParams.params.ex_iskeydown, remapParams.params.key, FlagStatus::makeFlags(), fromKey_.key, fromKey_.flags)) return false; remapParams.isremapped = true; // ------------------------------------------------------------ // handle EventType & Modifiers // Let's consider the following setting. // __KeyToKey__ KeyCode::SHIFT_R, ModifierFlag::SHIFT_R | ModifierFlag::NONE, KeyCode::A, ModifierFlag::SHIFT_R // In this setting, we need decrease SHIFT_R only once. // So, we transform values of fromKey_. // // [before] // fromKey_.key : KeyCode::SHIFT_R // fromKey_.flags : ModifierFlag::SHIFT_R | ModifierFlag::NONE // // [after] // fromKey_.key : KeyCode::SHIFT_R // fromKey_.flags : ModifierFlag::NONE // // Note: we need to apply this transformation after calling fromkeychecker_.isFromKey. Flags fromFlags = fromKey_.flags; fromFlags.remove(fromKey_.key.getModifierFlag()); if (remapParams.params.ex_iskeydown) { retractInput(); } else { restoreInput(); } // ---------------------------------------- // Handle beforeKeys_ if (remapParams.params.ex_iskeydown) { FlagStatus::temporary_decrease(fromFlags); for (size_t i = 0; i < beforeKeys_.size(); ++i) { FlagStatus::temporary_increase(beforeKeys_[i].flags); Flags f = FlagStatus::makeFlags(); KeyboardType keyboardType = remapParams.params.keyboardType; EventOutputQueue::FireKey::fire_downup(f, beforeKeys_[i].key, keyboardType); FlagStatus::temporary_decrease(beforeKeys_[i].flags); } FlagStatus::temporary_increase(fromFlags); } // ---------------------------------------- // Handle toKeys_ switch (toKeys_.size()) { case 0: break; case 1: { EventType newEventType = remapParams.params.ex_iskeydown ? EventType::DOWN : EventType::UP; KeyCode toKey = toKeys_[0].key; ModifierFlag toModifierFlag = toKey.getModifierFlag(); if (toModifierFlag == ModifierFlag::NONE && ! VirtualKey::isKeyLikeModifier(toKey)) { // toKey FlagStatus::temporary_decrease(fromFlags); FlagStatus::temporary_increase(toKeys_[0].flags); } else { // toModifier or VirtualKey::isKeyLikeModifier if (toModifierFlag != ModifierFlag::NONE) { newEventType = EventType::MODIFY; } if (remapParams.params.ex_iskeydown) { FlagStatus::increase(toKeys_[0].flags | toModifierFlag); FlagStatus::decrease(fromFlags); } else { FlagStatus::decrease(toKeys_[0].flags | toModifierFlag); FlagStatus::increase(fromFlags); } } // ---------------------------------------- Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(newEventType, FlagStatus::makeFlags(), toKey, remapParams.params.keyboardType, remapParams.params.repeat)); if (! ptr) return false; Params_KeyboardEventCallBack& params = *ptr; if (remapParams.params.ex_iskeydown && ! isRepeatEnabled_) { KeyboardRepeat::cancel(); } else { KeyboardRepeat::set(params); } EventOutputQueue::FireKey::fire(params); break; } default: KeyCode lastKey = toKeys_[toKeys_.size() - 1].key; Flags lastKeyFlags = toKeys_[toKeys_.size() - 1].flags; ModifierFlag lastKeyModifierFlag = lastKey.getModifierFlag(); bool isLastKeyModifier = (lastKeyModifierFlag != ModifierFlag::NONE); bool isLastKeyLikeModifier = VirtualKey::isKeyLikeModifier(lastKey); if (remapParams.params.ex_iskeydown) { KeyboardRepeat::cancel(); FlagStatus::temporary_decrease(fromFlags); size_t size = toKeys_.size(); // If the last key is modifier, we give it special treatment. // - Don't fire key repeat. // - Synchronous the key press status and the last modifier status. if (isLastKeyModifier || isLastKeyLikeModifier) { --size; } for (size_t i = 0; i < size; ++i) { FlagStatus::temporary_increase(toKeys_[i].flags); Flags f = FlagStatus::makeFlags(); KeyboardType keyboardType = remapParams.params.keyboardType; EventOutputQueue::FireKey::fire_downup(f, toKeys_[i].key, keyboardType); KeyboardRepeat::primitive_add_downup(f, toKeys_[i].key, keyboardType); FlagStatus::temporary_decrease(toKeys_[i].flags); } if (isLastKeyModifier || isLastKeyLikeModifier) { // restore temporary flag. FlagStatus::temporary_increase(fromFlags); FlagStatus::increase(lastKeyFlags | lastKeyModifierFlag); FlagStatus::decrease(fromFlags); if (isLastKeyLikeModifier) { // Don't call EventOutputQueue::FireModifiers::fire here. // // Intentionally VK_LAZY_* stop sending MODIFY events. // EventOutputQueue::FireModifiers::fire destroys this behavior. Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(EventType::DOWN, FlagStatus::makeFlags(), lastKey, remapParams.params.keyboardType, false)); if (ptr) { EventOutputQueue::FireKey::fire(*ptr); } } else { EventOutputQueue::FireModifiers::fire(); } } if (isLastKeyModifier || isLastKeyLikeModifier) { KeyboardRepeat::cancel(); } else { if (isRepeatEnabled_) { keyboardRepeatID_ = KeyboardRepeat::primitive_start(); } else { keyboardRepeatID_ = -1; } } } else { if (isLastKeyModifier || isLastKeyLikeModifier) { // For Lazy-Modifiers (KeyCode::VK_LAZY_*), // we need to handle these keys before restoring fromFlags, lastKeyFlags and lastKeyModifierFlag. // The unnecessary modifier events occur unless we do it. if (isLastKeyLikeModifier) { Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(EventType::UP, FlagStatus::makeFlags(), lastKey, remapParams.params.keyboardType, false)); if (ptr) { EventOutputQueue::FireKey::fire(*ptr); } } FlagStatus::decrease(lastKeyFlags | lastKeyModifierFlag); FlagStatus::increase(fromFlags); EventOutputQueue::FireModifiers::fire(); } else { if (KeyboardRepeat::getID() == keyboardRepeatID_) { KeyboardRepeat::cancel(); } } } break; } // ---------------------------------------- // Handle afterKeys_ if (! remapParams.params.ex_iskeydown) { // We need to keep temporary flags for "general.lazy_modifiers_with_mouse_event" when afterKeys_ is empty. if (afterKeys_.size() > 0) { // clear temporary flags. FlagStatus::set(); FlagStatus::temporary_decrease(fromFlags); for (size_t i = 0; i < afterKeys_.size(); ++i) { FlagStatus::temporary_increase(afterKeys_[i].flags); Flags f = FlagStatus::makeFlags(); KeyboardType keyboardType = remapParams.params.keyboardType; EventOutputQueue::FireKey::fire_downup(f, afterKeys_[i].key, keyboardType); FlagStatus::temporary_decrease(afterKeys_[i].flags); } FlagStatus::temporary_increase(fromFlags); } } return true; }
void add(KeyToKeyType::Value type, KeyCode newval) { add(type, AddDataType(BRIDGE_DATATYPE_KEYCODE), AddValue(newval.get())); }
// ====================================================================== void EventOutputQueue::FireKey::fire(const Params_KeyboardEventCallBack& params, AutogenId autogenId, PhysicalEventType physicalEventType) { if (VirtualKey::handle(params, autogenId, physicalEventType)) { CommonData::setcurrent_lastsentevent(params); return; } // ------------------------------------------------------------ KeyCode newkeycode = params.key; Flags newflags = params.flags; KeyCode::reverseNormalizeKey(newkeycode, newflags, params.eventType, params.keyboardType); // skip no-outputable keycodes. // Note: check before FireModifiers to avoid meaningless modifier event. if (newkeycode == KeyCode::VK_NONE || newkeycode == KeyCode::VK_PSEUDO_KEY) { // Do not call CommonData::setcurrent_lastsentevent. return; } if (newkeycode.isModifier() && newkeycode.getModifierFlag().getRawBits() == 0) { // virtual modifiers. CommonData::setcurrent_lastsentevent(params); return; } // Keep last modifier flags at EventType::UP to avoid unnecessary modifier events. // // For example, consider these rules: // // * Change Shift-N to Control-N // * Change Shift-P to Control-P // // <autogen>__KeyToKey__ KeyCode::N, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_SHIFT, KeyCode::N, ModifierFlag::CONTROL_L</autogen> // <autogen>__KeyToKey__ KeyCode::P, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_SHIFT, KeyCode::P, ModifierFlag::CONTROL_L</autogen> // // Case 1: // Actual input: // 1. shift down // 2. p down // 3. p up // 4. n down // 5. n up // 6. shift up // // Desirable results: // 1. shift down // 2. shift up, control down, p down // 3. p up // 4. n down // 5. n up // 6. control up // // // Case 2: // Actual input: // 1. shift down // 2. p down // 3. command down // 4. p up // 5. shift up // 6. command up // // Desirable results: // 1. shift down // 2. shift up, control down, p down // 3. control up, command down, shift down (== shift-command) // 4. p up // 5. shift up // 6. command up // // // Case 3: // Actual input: // 1. shift down // 2. p down // 3. shift up // 4. p up // // Desirable results: // 1. shift down // 2. shift up, control down, p down // 3. control up // 4. p up // // // Case 4: // Actual input: // 1. shift down // 2. e down // 3. p down // 4. e up // 5. p up // 6. shift up // // Desirable results: // 1. shift down // 2. e down // 3. shift up, control down, p down // 4. e up // 5. p up // 6. control up if (params.eventType == EventType::UP) { newflags = FireModifiers::getLastFlags(); } else { if (params.ex_iskeydown) { FireModifiers::setIgnorePhysicalUpEvent(false); } FireModifiers::fire(autogenId, physicalEventType, newflags, params.keyboardType); } if (params.eventType == EventType::DOWN || params.eventType == EventType::UP) { Params_KeyboardEventCallBack p(params.eventType, newflags, newkeycode, params.charCode, params.charSet, params.origCharCode, params.origCharSet, params.keyboardType, params.repeat); EventOutputQueue::push(p, autogenId); if (!params.repeat) { if (params.eventType == EventType::DOWN) { PressDownKeys::add(newkeycode, params.keyboardType); } else { PressDownKeys::remove(newkeycode, params.keyboardType); } } } }
// ---------------------------------------- // utility functions void add(KeyCode newval) { add(BRIDGE_DATATYPE_KEYCODE, newval.get()); }
// utility void add(KeyCode newval) { add(AddDataType(BRIDGE_DATATYPE_KEYCODE), AddValue(newval.get())); }
bool operator>=(KeyCode other) const { return value_ >= other.get(); }