예제 #1
0
TEST(Flags, stripEXTRA) {
  Flags mask = ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_R | ModifierFlag::COMMAND_R;
  Flags flags = mask;
  EXPECT_EQ(mask, flags.stripEXTRA());

  flags.add(ModifierFlag::EXTRA1);
  EXPECT_EQ(mask, flags.stripEXTRA());

  flags.add(ModifierFlag::EXTRA2);
  EXPECT_EQ(mask, flags.stripEXTRA());

  flags.add(ModifierFlag::EXTRA3 | ModifierFlag::EXTRA5);
  EXPECT_EQ(mask, flags.stripEXTRA());
}
  // ======================================================================
  void
  EventOutputQueue::FireKey::fire(const Params_KeyboardEventCallBack& params)
  {
    if (VirtualKey::handle(params)) return;

    // ----------------------------------------
    if (params.key == KeyCode::VK_MODIFIER_EXTRA1 ||
        params.key == KeyCode::VK_MODIFIER_EXTRA2 ||
        params.key == KeyCode::VK_MODIFIER_EXTRA3 ||
        params.key == KeyCode::VK_MODIFIER_EXTRA4 ||
        params.key == KeyCode::VK_MODIFIER_EXTRA5) return;

    // ------------------------------------------------------------
    KeyCode newkeycode = params.key;
    Flags newflags = params.flags;

    KeyCode::reverseNormalizeKey(newkeycode, newflags, params.eventType, params.keyboardType);
    newflags.stripEXTRA();

    // skip no-outputable keycodes.
    // Note: check before FireModifiers to avoid meaningless modifier event.
    if (newkeycode == KeyCode::VK_NONE ||
        newkeycode == KeyCode::VK_PSEUDO_KEY) {
      return;
    }

    FireModifiers::fire(newflags, params.keyboardType);

    if (params.eventType == EventType::DOWN || params.eventType == EventType::UP) {
      Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(params.eventType, newflags, newkeycode,
                                                                                     params.charCode, params.charSet, params.origCharCode, params.origCharSet,
                                                                                     params.keyboardType, params.repeat));
      if (ptr) {
        EventOutputQueue::push(*ptr);
      }

      if (! params.repeat) {
        if (params.eventType == EventType::DOWN) {
          PressDownKeys::add(newkeycode, params.keyboardType);
        } else {
          PressDownKeys::remove(newkeycode, params.keyboardType);
        }
      }
    }
  }
  // ======================================================================
  void
  EventOutputQueue::FireConsumer::fire(const Params_KeyboardSpecialEventCallback& params)
  {
    Flags newflags = params.flags;
    newflags.stripEXTRA();

    // skip no-outputable keycodes.
    // Note: check before FireModifiers to avoid meaningless modifier event.
    if (params.key == ConsumerKeyCode::VK_NONE ||
        params.key == ConsumerKeyCode::VK_PSEUDO_KEY) {
      return;
    }

    FireModifiers::fire();

    Params_KeyboardSpecialEventCallback::auto_ptr ptr(Params_KeyboardSpecialEventCallback::alloc(params.eventType, newflags, params.key, params.repeat));
    if (ptr) {
      EventOutputQueue::push(*ptr);
    }
  }
  void
  EventOutputQueue::FireModifiers::fire(Flags toFlags, KeyboardType keyboardType)
  {
    toFlags.stripNONE();
    toFlags.stripEXTRA();

    if (lastFlags_ == toFlags) return;

    // ------------------------------------------------------------
    // At first we handle KeyUp events and handle KeyDown events next.
    // We need to end KeyDown at Command+Space to Option_L+Shift_L.
    //
    // When Option_L+Shift_L has a meaning (switch input language at Windows),
    // it does not works well when the last is KeyUp of Command.

    // ------------------------------------------------------------
    // About ModifierFlag::CURSOR (UpdateEventFlags) handling:
    //
    // We need to treat ModifierFlag::CURSOR specially.
    //
    // When we activated "Control+Right to Option+Right" and pressed Control+Right,
    // the following events are happened.
    //
    // ----------------------+----------------------------------------------------------------------
    // (1) Press Control_L   | eventType:keyMod  code:0x3b name:Control_L flags:               misc:
    // (2) Press Right       | eventType:keyMod  code:0x3a name:Option_L  flags:Opt            misc:
    //                       | eventType:keyDown code:0x7c name:Right     flags:Opt NumPad Fn  misc:
    // (3) Release Right     | eventType:keyUp   code:0x7c name:Right     flags:Opt NumPad Fn  misc:
    // (4) Release Control_L | eventType:keyMod  code:0x3a name:Option_L  flags:               misc:
    // ----------------------+----------------------------------------------------------------------
    //
    // We need to treat "ModifierFlag::CURSOR Down" event after other modifiers.
    // We need to treat "ModifierFlag::CURSOR Up" event before other modifiers.
    // If not, unnecessary ModifierFlag::CURSOR is added on keyMod events.

    // ModifierFlag::CURSOR (Up)
    if (lastFlags_.isOn(ModifierFlag::CURSOR) && ! toFlags.isOn(ModifierFlag::CURSOR)) {
      lastFlags_.remove(ModifierFlag::CURSOR);

      Params_UpdateEventFlagsCallback::auto_ptr ptr(Params_UpdateEventFlagsCallback::alloc(lastFlags_));
      if (ptr) {
        EventOutputQueue::push(*ptr);
      }
    }

    // ------------------------------------------------------------
    // KeyUp
    for (int i = 0;; ++i) {
      ModifierFlag flag = FlagStatus::getFlag(i);
      if (flag == ModifierFlag::NONE) break;
      if (flag == ModifierFlag::CURSOR) continue;
      if (Flags(flag).isVirtualModifiersOn()) continue;

      if (! lastFlags_.isOn(flag)) continue;
      if (toFlags.isOn(flag)) continue;

      lastFlags_.remove(flag);

      Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(EventType::MODIFY, lastFlags_, flag.getKeyCode(), keyboardType, false));
      if (! ptr) continue;
      EventOutputQueue::push(*ptr);
    }

    // KeyDown
    for (int i = 0;; ++i) {
      ModifierFlag flag = FlagStatus::getFlag(i);
      if (flag == ModifierFlag::NONE) break;
      if (flag == ModifierFlag::CURSOR) continue;
      if (Flags(flag).isVirtualModifiersOn()) continue;

      if (! toFlags.isOn(flag)) continue;
      if (lastFlags_.isOn(flag)) continue;

      lastFlags_.add(flag);

      Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(EventType::MODIFY, lastFlags_, flag.getKeyCode(), keyboardType, false));
      if (! ptr) continue;
      EventOutputQueue::push(*ptr);
    }

    // ------------------------------------------------------------
    // ModifierFlag::CURSOR (Down)
    if (! lastFlags_.isOn(ModifierFlag::CURSOR) && toFlags.isOn(ModifierFlag::CURSOR)) {
      lastFlags_.add(ModifierFlag::CURSOR);

      Params_UpdateEventFlagsCallback::auto_ptr ptr(Params_UpdateEventFlagsCallback::alloc(lastFlags_));
      if (ptr) {
        EventOutputQueue::push(*ptr);
      }
    }

    lastFlags_ = toFlags;
  }