1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/base/ime/win/tsf_input_scope.h"
9 #include "base/compiler_specific.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/win/windows_version.h"
15 namespace tsf_inputscope
{
18 void AppendNonTrivialInputScope(std::vector
<InputScope
>* input_scopes
,
19 InputScope input_scope
) {
22 if (input_scope
== IS_DEFAULT
)
25 if (std::find(input_scopes
->begin(), input_scopes
->end(), input_scope
) !=
29 input_scopes
->push_back(input_scope
);
32 class TSFInputScope final
: public ITfInputScope
{
34 explicit TSFInputScope(const std::vector
<InputScope
>& input_scopes
)
35 : input_scopes_(input_scopes
),
39 STDMETHOD_(ULONG
, AddRef
)() override
{
40 return InterlockedIncrement(&ref_count_
);
43 STDMETHOD_(ULONG
, Release
)() override
{
44 const LONG count
= InterlockedDecrement(&ref_count_
);
49 return static_cast<ULONG
>(count
);
52 STDMETHOD(QueryInterface
)(REFIID iid
, void** result
) override
{
55 if (iid
== IID_IUnknown
|| iid
== IID_ITfInputScope
) {
56 *result
= static_cast<ITfInputScope
*>(this);
65 STDMETHOD(GetInputScopes
)(InputScope
** input_scopes
, UINT
* count
) override
{
66 if (!count
|| !input_scopes
)
68 *input_scopes
= static_cast<InputScope
*>(CoTaskMemAlloc(
69 sizeof(InputScope
) * input_scopes_
.size()));
75 for (size_t i
= 0; i
< input_scopes_
.size(); ++i
)
76 (*input_scopes
)[i
] = input_scopes_
[i
];
77 *count
= input_scopes_
.size();
81 STDMETHOD(GetPhrase
)(BSTR
** phrases
, UINT
* count
) override
{
85 STDMETHOD(GetRegularExpression
)(BSTR
* regexp
) override
{
89 STDMETHOD(GetSRGS
)(BSTR
* srgs
) override
{
93 STDMETHOD(GetXML
)(BSTR
* xml
) override
{
98 // The corresponding text input types.
99 std::vector
<InputScope
> input_scopes_
;
101 // The refrence count of this instance.
102 volatile LONG ref_count_
;
104 DISALLOW_COPY_AND_ASSIGN(TSFInputScope
);
107 typedef HRESULT (WINAPI
*SetInputScopesFunc
)(HWND window_handle
,
108 const InputScope
* input_scope_list
,
109 UINT num_input_scopes
,
110 WCHAR
**, /* unused */
113 WCHAR
* /* unused */);
115 SetInputScopesFunc g_set_input_scopes
= NULL
;
116 bool g_get_proc_done
= false;
118 SetInputScopesFunc
GetSetInputScopes() {
119 DCHECK(base::MessageLoopForUI::IsCurrent());
120 // Thread safety is not required because this function is under UI thread.
121 if (!g_get_proc_done
) {
122 g_get_proc_done
= true;
124 // For stability reasons, we do not support Windows XP.
125 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
128 HMODULE module
= NULL
;
129 if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
, L
"msctf.dll",
133 g_set_input_scopes
= reinterpret_cast<SetInputScopesFunc
>(
134 GetProcAddress(module
, "SetInputScopes"));
136 return g_set_input_scopes
;
139 InputScope
ConvertTextInputTypeToInputScope(TextInputType text_input_type
) {
140 // Following mapping is based in IE10 on Windows 8.
141 switch (text_input_type
) {
142 case TEXT_INPUT_TYPE_PASSWORD
:
144 case TEXT_INPUT_TYPE_SEARCH
:
146 case TEXT_INPUT_TYPE_EMAIL
:
147 return IS_EMAIL_SMTPEMAILADDRESS
;
148 case TEXT_INPUT_TYPE_NUMBER
:
150 case TEXT_INPUT_TYPE_TELEPHONE
:
151 return IS_TELEPHONE_FULLTELEPHONENUMBER
;
152 case TEXT_INPUT_TYPE_URL
:
159 InputScope
ConvertTextInputModeToInputScope(TextInputMode text_input_mode
) {
160 switch (text_input_mode
) {
161 case TEXT_INPUT_MODE_FULL_WIDTH_LATIN
:
162 return IS_ALPHANUMERIC_FULLWIDTH
;
163 case TEXT_INPUT_MODE_KANA
:
165 case TEXT_INPUT_MODE_KATAKANA
:
166 return IS_KATAKANA_FULLWIDTH
;
167 case TEXT_INPUT_MODE_NUMERIC
:
169 case TEXT_INPUT_MODE_TEL
:
170 return IS_TELEPHONE_FULLTELEPHONENUMBER
;
171 case TEXT_INPUT_MODE_EMAIL
:
172 return IS_EMAIL_SMTPEMAILADDRESS
;
173 case TEXT_INPUT_MODE_URL
:
182 std::vector
<InputScope
> GetInputScopes(TextInputType text_input_type
,
183 TextInputMode text_input_mode
) {
184 std::vector
<InputScope
> input_scopes
;
186 AppendNonTrivialInputScope(&input_scopes
,
187 ConvertTextInputTypeToInputScope(text_input_type
));
188 AppendNonTrivialInputScope(&input_scopes
,
189 ConvertTextInputModeToInputScope(text_input_mode
));
191 if (input_scopes
.empty())
192 input_scopes
.push_back(IS_DEFAULT
);
197 ITfInputScope
* CreateInputScope(TextInputType text_input_type
,
198 TextInputMode text_input_mode
) {
199 return new TSFInputScope(GetInputScopes(text_input_type
, text_input_mode
));
202 void SetInputScopeForTsfUnawareWindow(
204 TextInputType text_input_type
,
205 TextInputMode text_input_mode
) {
206 SetInputScopesFunc set_input_scopes
= GetSetInputScopes();
207 if (!set_input_scopes
)
210 std::vector
<InputScope
> input_scopes
= GetInputScopes(text_input_type
,
212 set_input_scopes(window_handle
, &input_scopes
[0], input_scopes
.size(), NULL
,
216 } // namespace tsf_inputscope