void KeyboardEvent::GetInitDict(KeyboardEventInit& aParam)
{
  GetKey(aParam.mKey);
  GetCode(aParam.mCode);
  aParam.mLocation = Location();
  aParam.mRepeat = Repeat();
  aParam.mIsComposing = IsComposing();

  // legacy attributes
  aParam.mKeyCode = KeyCode();
  aParam.mCharCode = CharCode();
  aParam.mWhich = Which();

  // modifiers from EventModifierInit
  aParam.mCtrlKey = CtrlKey();
  aParam.mShiftKey = ShiftKey();
  aParam.mAltKey = AltKey();
  aParam.mMetaKey = MetaKey();

  WidgetKeyboardEvent* internalEvent = mEvent->AsKeyboardEvent();
  aParam.mModifierAltGraph = internalEvent->IsAltGraph();
  aParam.mModifierCapsLock = internalEvent->IsCapsLocked();
  aParam.mModifierFn = internalEvent->IsFn();
  aParam.mModifierFnLock = internalEvent->IsFnLocked();
  aParam.mModifierNumLock = internalEvent->IsNumLocked();
  aParam.mModifierOS = internalEvent->IsOS();
  aParam.mModifierScrollLock = internalEvent->IsScrollLocked();
  aParam.mModifierSymbol = internalEvent->IsSymbol();
  aParam.mModifierSymbolLock = internalEvent->IsSymbolLocked();

  // EventInit
  aParam.mBubbles =  internalEvent->mFlags.mBubbles;
  aParam.mCancelable = internalEvent->mFlags.mCancelable;
}
Example #2
0
bool
nsXBLKeyEventHandler::ExecuteMatchedHandlers(
                        nsIDOMKeyEvent* aKeyEvent,
                        uint32_t aCharCode,
                        const IgnoreModifierState& aIgnoreModifierState)
{
  WidgetEvent* event = aKeyEvent->GetInternalNSEvent();
  nsCOMPtr<EventTarget> target = aKeyEvent->InternalDOMEvent()->GetCurrentTarget();

  bool executed = false;
  for (uint32_t i = 0; i < mProtoHandlers.Length(); ++i) {
    nsXBLPrototypeHandler* handler = mProtoHandlers[i];
    bool hasAllowUntrustedAttr = handler->HasAllowUntrustedAttr();
    if ((event->mFlags.mIsTrusted ||
        (hasAllowUntrustedAttr && handler->AllowUntrustedEvents()) ||
        (!hasAllowUntrustedAttr && !mIsBoundToChrome && !mUsingContentXBLScope)) &&
        handler->KeyEventMatched(aKeyEvent, aCharCode, aIgnoreModifierState)) {
      handler->ExecuteHandler(target, aKeyEvent);
      executed = true;
    }
  }
#ifdef XP_WIN
  // Windows native applications ignore Windows-Logo key state when checking
  // shortcut keys even if the key is pressed.  Therefore, if there is no
  // shortcut key which exactly matches current modifier state, we should
  // retry to look for a shortcut key without the Windows-Logo key press.
  if (!executed && !aIgnoreModifierState.mOS) {
    WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent();
    if (keyEvent && keyEvent->IsOS()) {
      IgnoreModifierState ignoreModifierState(aIgnoreModifierState);
      ignoreModifierState.mOS = true;
      return ExecuteMatchedHandlers(aKeyEvent, aCharCode, ignoreModifierState);
    }
  }
#endif
  return executed;
}
bool
nsXBLWindowKeyHandler::WalkHandlersAndExecute(
                         nsIDOMKeyEvent* aKeyEvent,
                         nsIAtom* aEventType,
                         nsXBLPrototypeHandler* aHandler,
                         uint32_t aCharCode,
                         const IgnoreModifierState& aIgnoreModifierState,
                         bool aExecute,
                         bool* aOutReservedForChrome)
{
  nsresult rv;

  // Try all of the handlers until we find one that matches the event.
  for (nsXBLPrototypeHandler *currHandler = aHandler; currHandler;
       currHandler = currHandler->GetNextHandler()) {
    bool stopped = aKeyEvent->AsEvent()->IsDispatchStopped();
    if (stopped) {
      // The event is finished, don't execute any more handlers
      return false;
    }

    if (!EventMatched(currHandler, aEventType, aKeyEvent,
                      aCharCode, aIgnoreModifierState)) {
      continue;  // try the next one
    }

    // Before executing this handler, check that it's not disabled,
    // and that it has something to do (oncommand of the <key> or its
    // <command> is non-empty).
    nsCOMPtr<nsIContent> elt = currHandler->GetHandlerElement();
    nsCOMPtr<Element> commandElt;

    // See if we're in a XUL doc.
    nsCOMPtr<Element> el = GetElement();
    if (el && elt) {
      // We are.  Obtain our command attribute.
      nsAutoString command;
      elt->GetAttr(kNameSpaceID_None, nsGkAtoms::command, command);
      if (!command.IsEmpty()) {
        // Locate the command element in question.  Note that we
        // know "elt" is in a doc if we're dealing with it here.
        NS_ASSERTION(elt->IsInDoc(), "elt must be in document");
        nsIDocument *doc = elt->GetCurrentDoc();
        if (doc)
          commandElt = do_QueryInterface(doc->GetElementById(command));

        if (!commandElt) {
          NS_ERROR("A XUL <key> is observing a command that doesn't exist. Unable to execute key binding!");
          continue;
        }
      }
    }

    if (!commandElt) {
      commandElt = do_QueryInterface(elt);
    }

    if (commandElt) {
      nsAutoString value;
      commandElt->GetAttribute(NS_LITERAL_STRING("disabled"), value);
      if (value.EqualsLiteral("true")) {
        continue;  // this handler is disabled, try the next one
      }

      // Check that there is an oncommand handler
      commandElt->GetAttribute(NS_LITERAL_STRING("oncommand"), value);
      if (value.IsEmpty()) {
        continue;  // nothing to do
      }

      if (aOutReservedForChrome) {
        // The caller wants to know if this is a reserved command
        commandElt->GetAttribute(NS_LITERAL_STRING("reserved"), value);
        *aOutReservedForChrome = value.EqualsLiteral("true");
      }
    }

    nsCOMPtr<EventTarget> piTarget;
    nsCOMPtr<Element> element = GetElement();
    if (element) {
      piTarget = commandElt;
    } else {
      piTarget = mTarget;
    }

    if (!aExecute) {
      return true;
    }

    rv = currHandler->ExecuteHandler(piTarget, aKeyEvent->AsEvent());
    if (NS_SUCCEEDED(rv)) {
      return true;
    }
  }

#ifdef XP_WIN
  // Windows native applications ignore Windows-Logo key state when checking
  // shortcut keys even if the key is pressed.  Therefore, if there is no
  // shortcut key which exactly matches current modifier state, we should
  // retry to look for a shortcut key without the Windows-Logo key press.
  if (!aIgnoreModifierState.mOS) {
    WidgetKeyboardEvent* keyEvent =
      aKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
    if (keyEvent && keyEvent->IsOS()) {
      IgnoreModifierState ignoreModifierState(aIgnoreModifierState);
      ignoreModifierState.mOS = true;
      return WalkHandlersAndExecute(aKeyEvent, aEventType, aHandler, aCharCode,
                                    ignoreModifierState, aExecute);
    }
  }
#endif

  return false;
}
bool
nsXBLWindowKeyHandler::WalkHandlersAndExecute(
                         nsIDOMKeyEvent* aKeyEvent,
                         nsIAtom* aEventType,
                         nsXBLPrototypeHandler* aFirstHandler,
                         uint32_t aCharCode,
                         const IgnoreModifierState& aIgnoreModifierState,
                         bool aExecute,
                         bool* aOutReservedForChrome)
{
  // Try all of the handlers until we find one that matches the event.
  for (nsXBLPrototypeHandler* handler = aFirstHandler;
       handler;
       handler = handler->GetNextHandler()) {
    bool stopped = aKeyEvent->AsEvent()->IsDispatchStopped();
    if (stopped) {
      // The event is finished, don't execute any more handlers
      return false;
    }

    if (aExecute) {
      // If it's executing matched handlers, the event type should exactly be
      // matched.
      if (!handler->EventTypeEquals(aEventType)) {
        continue;
      }
    } else {
      if (handler->EventTypeEquals(nsGkAtoms::keypress)) {
        // If the handler is a keypress event handler, we also need to check
        // if coming keydown event is a preceding event of reserved key
        // combination because if default action of a keydown event is
        // prevented, following keypress event won't be fired.  However, if
        // following keypress event is reserved, we shouldn't allow web
        // contents to prevent the default of the preceding keydown event.
        if (aEventType != nsGkAtoms::keydown &&
            aEventType != nsGkAtoms::keypress) {
          continue;
        }
      } else if (!handler->EventTypeEquals(aEventType)) {
        // Otherwise, aEventType should exactly be matched.
        continue;
      }
    }

    // Check if the keyboard event *may* execute the handler.
    if (!handler->KeyEventMatched(aKeyEvent, aCharCode, aIgnoreModifierState)) {
      continue;  // try the next one
    }

    // Before executing this handler, check that it's not disabled,
    // and that it has something to do (oncommand of the <key> or its
    // <command> is non-empty).
    nsCOMPtr<Element> commandElement;
    if (!GetElementForHandler(handler, getter_AddRefs(commandElement))) {
      continue;
    }

    bool isReserved = false;
    if (commandElement) {
      if (!IsExecutableElement(commandElement)) {
        continue;
      }

      isReserved =
        commandElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::reserved,
                                    nsGkAtoms::_true, eCaseMatters);
      if (aOutReservedForChrome) {
        *aOutReservedForChrome = isReserved;
      }
    }

    if (!aExecute) {
      if (handler->EventTypeEquals(aEventType)) {
        return true;
      }
      // If the command is reserved and the event is keydown, check also if
      // the handler is for keypress because if following keypress event is
      // reserved, we shouldn't dispatch the event into web contents.
      if (isReserved &&
          aEventType == nsGkAtoms::keydown &&
          handler->EventTypeEquals(nsGkAtoms::keypress)) {
        return true;
      }
      // Otherwise, we've not found a handler for the event yet.
      continue;
    }

    nsCOMPtr<EventTarget> target;
    nsCOMPtr<Element> chromeHandlerElement = GetElement();
    if (chromeHandlerElement) {
      // XXX commandElement may be nullptr...
      target = commandElement;
    } else {
      target = mTarget;
    }

    // XXX Do we execute only one handler even if the handler neither stops
    //     propagation nor prevents default of the event?
    nsresult rv = handler->ExecuteHandler(target, aKeyEvent->AsEvent());
    if (NS_SUCCEEDED(rv)) {
      return true;
    }
  }

#ifdef XP_WIN
  // Windows native applications ignore Windows-Logo key state when checking
  // shortcut keys even if the key is pressed.  Therefore, if there is no
  // shortcut key which exactly matches current modifier state, we should
  // retry to look for a shortcut key without the Windows-Logo key press.
  if (!aIgnoreModifierState.mOS) {
    WidgetKeyboardEvent* keyEvent =
      aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
    if (keyEvent && keyEvent->IsOS()) {
      IgnoreModifierState ignoreModifierState(aIgnoreModifierState);
      ignoreModifierState.mOS = true;
      return WalkHandlersAndExecute(aKeyEvent, aEventType, aFirstHandler,
                                    aCharCode, ignoreModifierState, aExecute);
    }
  }
#endif

  return false;
}