Bug 1240208 - use inputmode in XUL to get better hinting for IME and on-screen keyboards, r?masayuki
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -32,17 +32,18 @@ file, You can obtain one at http://mozil
</children>
<xul:hbox anonid="textbox-input-box"
class="textbox-input-box urlbar-input-box"
flex="1" xbl:inherits="tooltiptext=inputtooltiptext">
<children/>
<html:input anonid="input"
class="autocomplete-textbox urlbar-input textbox-input uri-element-right-align"
allowevents="true"
- xbl:inherits="tooltiptext=inputtooltiptext,value,type=inputtype,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/>
+ inputmode="url"
+ xbl:inherits="tooltiptext=inputtooltiptext,value,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/>
</xul:hbox>
<xul:dropmarker anonid="historydropmarker"
class="autocomplete-history-dropmarker urlbar-history-dropmarker"
tooltiptext="&urlbar.openHistoryPopup.tooltip;"
allowevents="true"
xbl:inherits="open,enablehistory,parentfocused=focused"/>
<children includes="hbox"/>
</xul:hbox>
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -1029,17 +1029,18 @@ IMEStateManager::SetIMEState(const IMESt
}
}
content->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
context.mHTMLInputType);
} else {
context.mHTMLInputType.Assign(nsGkAtoms::textarea->GetUTF16String());
}
- if (Preferences::GetBool("dom.forms.inputmode", false)) {
+ if (Preferences::GetBool("dom.forms.inputmode", false) ||
+ nsContentUtils::IsChromeDoc(aContent->OwnerDoc())) {
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::inputmode,
context.mHTMLInputInputmode);
}
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint,
context.mActionHint);
// Get the input content corresponding to the focused node,
--- a/widget/windows/TSFTextStore.cpp
+++ b/widget/windows/TSFTextStore.cpp
@@ -3023,20 +3023,31 @@ TSFTextStore::InsertEmbedded(DWORD dwFla
("TSF: 0x%p TSFTextStore::InsertEmbedded() called "
"but not supported (E_NOTIMPL)", this));
// embedded objects are not supported
return E_NOTIMPL;
}
void
-TSFTextStore::SetInputScope(const nsString& aHTMLInputType)
+TSFTextStore::SetInputScope(const nsString& aHTMLInputType,
+ const nsString& aHTMLInputInputMode)
{
mInputScopes.Clear();
if (aHTMLInputType.IsEmpty() || aHTMLInputType.EqualsLiteral("text")) {
+ if (aHTMLInputInputMode.EqualsLiteral("url")) {
+ mInputScopes.AppendElement(IS_URL);
+ } else if (aHTMLInputInputMode.EqualsLiteral("email")) {
+ mInputScopes.AppendElement(IS_EMAIL_SMTPEMAILADDRESS);
+ } else if (aHTMLInputType.EqualsLiteral("tel")) {
+ mInputScopes.AppendElement(IS_TELEPHONE_FULLTELEPHONENUMBER);
+ mInputScopes.AppendElement(IS_TELEPHONE_LOCALNUMBER);
+ } else if (aHTMLInputType.EqualsLiteral("numeric")) {
+ mInputScopes.AppendElement(IS_NUMBER);
+ }
return;
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html
if (aHTMLInputType.EqualsLiteral("url")) {
mInputScopes.AppendElement(IS_URL);
} else if (aHTMLInputType.EqualsLiteral("search")) {
mInputScopes.AppendElement(IS_SEARCH);
@@ -4554,17 +4565,18 @@ TSFTextStore::CreateAndSetFocus(nsWindow
sEnabledTextStore->mDocumentMgr,
getter_AddRefs(prevFocusedDocumentMgr));
if (NS_WARN_IF(FAILED(hr))) {
MOZ_LOG(sTextStoreLog, LogLevel::Error,
("TSF: TSFTextStore::CreateAndSetFocus() FAILED due to "
"ITfTheadMgr::AssociateFocus() failure"));
return false;
}
- sEnabledTextStore->SetInputScope(aContext.mHTMLInputType);
+ sEnabledTextStore->SetInputScope(aContext.mHTMLInputType,
+ aContext.mHTMLInputInputmode);
if (sEnabledTextStore->mSink) {
MOZ_LOG(sTextStoreLog, LogLevel::Info,
("TSF: TSFTextStore::CreateAndSetFocus(), calling "
"ITextStoreACPSink::OnLayoutChange(TS_LC_CREATE) for 0x%p...",
sEnabledTextStore.get()));
sEnabledTextStore->mSink->OnLayoutChange(TS_LC_CREATE,
TEXTSTORE_DEFAULT_VIEW);
@@ -5291,17 +5303,18 @@ TSFTextStore::SetInputContext(nsWindowBa
aWidget, GetIMEEnabledName(aContext.mIMEState.mEnabled),
GetFocusChangeName(aAction.mFocusChange), sEnabledTextStore.get(),
GetBoolName(ThinksHavingFocus())));
NS_ENSURE_TRUE_VOID(IsInTSFMode());
if (aAction.mFocusChange != InputContextAction::FOCUS_NOT_CHANGED) {
if (sEnabledTextStore) {
- sEnabledTextStore->SetInputScope(aContext.mHTMLInputType);
+ sEnabledTextStore->SetInputScope(aContext.mHTMLInputType,
+ aContext.mHTMLInputInputmode);
}
return;
}
// If focus isn't actually changed but the enabled state is changed,
// emulate the focus move.
if (!ThinksHavingFocus() && aContext.mIMEState.IsEditable()) {
OnFocusChange(true, aWidget, aContext);
--- a/widget/windows/TSFTextStore.h
+++ b/widget/windows/TSFTextStore.h
@@ -297,17 +297,18 @@ protected:
void NotifyTSFOfTextChange(const TS_TEXTCHANGE& aTextChange);
void NotifyTSFOfSelectionChange();
bool NotifyTSFOfLayoutChange();
void NotifyTSFOfLayoutChangeAgain();
HRESULT HandleRequestAttrs(DWORD aFlags,
ULONG aFilterCount,
const TS_ATTRID* aFilterAttrs);
- void SetInputScope(const nsString& aHTMLInputType);
+ void SetInputScope(const nsString& aHTMLInputType,
+ const nsString& aHTMLInputInputmode);
// Creates native caret over our caret. This method only works on desktop
// application. Otherwise, this does nothing.
void CreateNativeCaret();
// Destroys native caret if there is.
void MaybeDestroyNativeCaret();
// Holds the pointer to our current win32 widget
--- a/widget/windows/WinIMEHandler.cpp
+++ b/widget/windows/WinIMEHandler.cpp
@@ -388,17 +388,17 @@ IMEHandler::OnDestroyWindow(nsWindow* aW
}
#ifdef NS_ENABLE_TSF
// We need to do nothing here for TSF. Just restore the default context
// if it's been disassociated.
if (!sIsInTSFMode) {
// MSDN says we need to set IS_DEFAULT to avoid memory leak when we use
// SetInputScopes API. Use an empty string to do this.
- SetInputScopeForIMM32(aWindow, EmptyString());
+ SetInputScopeForIMM32(aWindow, EmptyString(), EmptyString());
}
#endif // #ifdef NS_ENABLE_TSF
AssociateIMEContext(aWindow, true);
}
// static
void
IMEHandler::SetInputContext(nsWindow* aWindow,
@@ -439,17 +439,18 @@ IMEHandler::SetInputContext(nsWindow* aW
}
if (adjustOpenState) {
TSFTextStore::SetIMEOpenState(open);
}
return;
}
} else {
// Set at least InputScope even when TextStore is not available.
- SetInputScopeForIMM32(aWindow, aInputContext.mHTMLInputType);
+ SetInputScopeForIMM32(aWindow, aInputContext.mHTMLInputType,
+ aInputContext.mHTMLInputInputmode);
}
#endif // #ifdef NS_ENABLE_TSF
AssociateIMEContext(aWindow, enable);
IMEContext context(aWindow);
if (adjustOpenState) {
context.SetOpenState(open);
@@ -512,28 +513,48 @@ IMEHandler::CurrentKeyboardLayoutHasIME(
return IMMHandler::IsIMEAvailable();
}
#endif // #ifdef DEBUG
// static
void
IMEHandler::SetInputScopeForIMM32(nsWindow* aWindow,
- const nsAString& aHTMLInputType)
+ const nsAString& aHTMLInputType,
+ const nsAString& aHTMLInputInputmode)
{
if (sIsInTSFMode || !sSetInputScopes || aWindow->Destroyed()) {
return;
}
UINT arraySize = 0;
const InputScope* scopes = nullptr;
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html
if (aHTMLInputType.IsEmpty() || aHTMLInputType.EqualsLiteral("text")) {
- static const InputScope inputScopes[] = { IS_DEFAULT };
- scopes = &inputScopes[0];
- arraySize = ArrayLength(inputScopes);
+ if (aHTMLInputInputmode.EqualsLiteral("url")) {
+ static const InputScope inputScopes[] = { IS_URL };
+ scopes = &inputScopes[0];
+ arraySize = ArrayLength(inputScopes);
+ } else if (aHTMLInputInputmode.EqualsLiteral("email")) {
+ static const InputScope inputScopes[] = { IS_EMAIL_SMTPEMAILADDRESS };
+ scopes = &inputScopes[0];
+ arraySize = ArrayLength(inputScopes);
+ } else if (aHTMLInputInputmode.EqualsLiteral("tel")) {
+ static const InputScope inputScopes[] =
+ {IS_TELEPHONE_LOCALNUMBER, IS_TELEPHONE_FULLTELEPHONENUMBER};
+ scopes = &inputScopes[0];
+ arraySize = ArrayLength(inputScopes);
+ } else if (aHTMLInputInputmode.EqualsLiteral("numeric")) {
+ static const InputScope inputScopes[] = { IS_NUMBER };
+ scopes = &inputScopes[0];
+ arraySize = ArrayLength(inputScopes);
+ } else {
+ static const InputScope inputScopes[] = { IS_DEFAULT };
+ scopes = &inputScopes[0];
+ arraySize = ArrayLength(inputScopes);
+ }
} else if (aHTMLInputType.EqualsLiteral("url")) {
static const InputScope inputScopes[] = { IS_URL };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
} else if (aHTMLInputType.EqualsLiteral("search")) {
static const InputScope inputScopes[] = { IS_SEARCH };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
--- a/widget/windows/WinIMEHandler.h
+++ b/widget/windows/WinIMEHandler.h
@@ -126,17 +126,18 @@ private:
static nsWindow* sFocusedWindow;
static InputContextAction::Cause sLastContextActionCause;
static bool sPluginHasFocus;
#ifdef NS_ENABLE_TSF
static decltype(SetInputScopes)* sSetInputScopes;
static void SetInputScopeForIMM32(nsWindow* aWindow,
- const nsAString& aHTMLInputType);
+ const nsAString& aHTMLInputType,
+ const nsAString& aHTMLInputInputmode);
static bool sIsInTSFMode;
// If sIMMEnabled is false, any IME messages are not handled in TSF mode.
// Additionally, IME context is always disassociated from focused window.
static bool sIsIMMEnabled;
static bool IsTSFAvailable() { return (sIsInTSFMode && !sPluginHasFocus); }
static bool IsIMMActive();