Beispiel #1
0
// ------------------------------------------------------------
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
    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
  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 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);
}
Beispiel #5
0
    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 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);
      }
    }
  }
}