Пример #1
0
void
IMEStateManager::SetIMEState(const IMEState& aState,
                             nsIContent* aContent,
                             nsIWidget* aWidget,
                             InputContextAction aAction)
{
    NS_ENSURE_TRUE_VOID(aWidget);

    InputContext oldContext = aWidget->GetInputContext();

    InputContext context;
    context.mIMEState = aState;

    if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML &&
            (aContent->Tag() == nsGkAtoms::input ||
             aContent->Tag() == nsGkAtoms::textarea)) {
        if (aContent->Tag() != nsGkAtoms::textarea) {
            // <input type=number> has an anonymous <input type=text> descendant
            // that gets focus whenever anyone tries to focus the number control. We
            // need to check if aContent is one of those anonymous text controls and,
            // if so, use the number control instead:
            nsIContent* content = aContent;
            HTMLInputElement* inputElement =
                HTMLInputElement::FromContentOrNull(aContent);
            if (inputElement) {
                HTMLInputElement* ownerNumberControl =
                    inputElement->GetOwnerNumberControl();
                if (ownerNumberControl) {
                    content = ownerNumberControl; // an <input type=number>
                }
            }
            content->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
                             context.mHTMLInputType);
        } else {
            context.mHTMLInputType.Assign(nsGkAtoms::textarea->GetUTF16String());
        }

        if (Preferences::GetBool("dom.forms.inputmode", false)) {
            aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::inputmode,
                              context.mHTMLInputInputmode);
        }

        aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint,
                          context.mActionHint);

        // if we don't have an action hint and  return won't submit the form use "next"
        if (context.mActionHint.IsEmpty() && aContent->Tag() == nsGkAtoms::input) {
            bool willSubmit = false;
            nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
            mozilla::dom::Element* formElement = control->GetFormElement();
            nsCOMPtr<nsIForm> form;
            if (control) {
                // is this a form and does it have a default submit element?
                if ((form = do_QueryInterface(formElement)) &&
                        form->GetDefaultSubmitElement()) {
                    willSubmit = true;
                    // is this an html form and does it only have a single text input element?
                } else if (formElement && formElement->Tag() == nsGkAtoms::form &&
                           formElement->IsHTML() &&
                           !static_cast<dom::HTMLFormElement*>(formElement)->
                           ImplicitSubmissionIsDisabled()) {
                    willSubmit = true;
                }
            }
            context.mActionHint.Assign(
                willSubmit ? (control->GetType() == NS_FORM_INPUT_SEARCH ?
                              NS_LITERAL_STRING("search") : NS_LITERAL_STRING("go")) :
                (formElement ?
                 NS_LITERAL_STRING("next") : EmptyString()));
        }
    }

    // XXX I think that we should use nsContentUtils::IsCallerChrome() instead
    //     of the process type.
    if (aAction.mCause == InputContextAction::CAUSE_UNKNOWN &&
            XRE_GetProcessType() != GeckoProcessType_Content) {
        aAction.mCause = InputContextAction::CAUSE_UNKNOWN_CHROME;
    }

    aWidget->SetInputContext(context, aAction);
    if (oldContext.mIMEState.mEnabled == context.mIMEState.mEnabled) {
        return;
    }

    nsContentUtils::AddScriptRunner(
        new IMEEnabledStateChangedEvent(context.mIMEState.mEnabled));
}