Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: views/ime/input_method_win.cc

Issue 6688049: New InputMethod api for Views. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address review feedbacks. Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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.
4
5 #include "views/ime/input_method_win.h"
6
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/string_util.h"
10 #include "ui/base/keycodes/keyboard_codes.h"
11 #include "views/events/event.h"
12
13 namespace views {
14
15 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate)
16 : active_(false),
17 direction_(base::i18n::UNKNOWN_DIRECTION),
18 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION) {
19 set_delegate(delegate);
20 }
21
22 InputMethodWin::~InputMethodWin() {
23 if (widget())
24 ime_input_.DisableIME(hwnd());
25 }
26
27 void InputMethodWin::Init(Widget* widget) {
28 InputMethodBase::Init(widget);
29
30 // Gets the initial input locale and text direction information.
31 OnInputLangChange(0, 0);
32 }
33
34 void InputMethodWin::DispatchKeyEvent(const KeyEvent& key) {
35 // Handles ctrl-shift key to change text direction and layout alignment.
36 if (ui::ImeInput::IsRTLKeyboardLayoutInstalled() && !IsTextInputTypeNone()) {
37 ui::KeyboardCode code = key.key_code();
38 if (key.type() == ui::ET_KEY_PRESSED) {
39 if (code == ui::VKEY_SHIFT) {
40 base::i18n::TextDirection dir;
41 if (ui::ImeInput::IsCtrlShiftPressed(&dir))
42 pending_requested_direction_ = dir;
43 } else if (code != ui::VKEY_CONTROL) {
44 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
45 }
46 } else if (key.type() == ui::ET_KEY_RELEASED &&
47 (code == ui::VKEY_SHIFT || code == ui::VKEY_CONTROL) &&
48 pending_requested_direction_ != base::i18n::UNKNOWN_DIRECTION) {
49 GetTextInputClient()->ChangeTextDirectionAndLayoutAlignment(
50 pending_requested_direction_);
51 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
52 }
53 }
54
55 DispatchKeyEventPostIME(key);
56 }
57
58 void InputMethodWin::OnTextInputTypeChanged(View* view) {
59 if (IsViewFocused(view)) {
60 ime_input_.CancelIME(hwnd());
61 UpdateIMEState();
62 }
63 }
64
65 void InputMethodWin::OnCaretBoundsChanged(View* view) {
66 gfx::Rect rect;
67 if (!IsViewFocused(view) || !GetCaretBoundsInWidget(&rect))
68 return;
69 ime_input_.UpdateCaretRect(hwnd(), rect);
70 }
71
72 void InputMethodWin::CancelComposition(View* view) {
73 if (IsViewFocused(view))
74 ime_input_.CancelIME(hwnd());
75 }
76
77 std::string InputMethodWin::GetInputLocale() {
78 return locale_;
79 }
80
81 base::i18n::TextDirection InputMethodWin::GetInputTextDirection() {
82 return direction_;
83 }
84
85 bool InputMethodWin::IsActive() {
86 return active_;
87 }
88
89 void InputMethodWin::FocusedViewWillChange() {
90 ConfirmCompositionText();
91 }
92
93 void InputMethodWin::FocusedViewDidChange() {
94 UpdateIMEState();
95 }
96
97 void InputMethodWin::OnSetFocus() {
98 if (!widget_focused()) {
99 set_widget_focused(true);
100 UpdateIMEState();
101 }
102 }
103
104 void InputMethodWin::OnKillFocus() {
105 if (widget_focused()) {
106 ConfirmCompositionText();
107 set_widget_focused(false);
108 }
109 }
110
111 void InputMethodWin::OnInputLangChange(DWORD character_set,
112 HKL input_language_id) {
113 active_ = ime_input_.SetInputLanguage();
114 locale_ = ime_input_.GetInputLanguageName();
115 direction_ = ime_input_.GetTextDirection();
116 OnInputMethodChanged();
117 }
118
119 LRESULT InputMethodWin::OnImeSetContext(
120 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
121 active_ = (wparam == TRUE);
122 if (active_)
123 ime_input_.CreateImeWindow(hwnd());
124
125 OnInputMethodChanged();
126 return ime_input_.SetImeWindowStyle(hwnd(), message, wparam, lparam, handled);
127 }
128
129 LRESULT InputMethodWin::OnImeStartComposition(
130 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
131 // We have to prevent WTL from calling ::DefWindowProc() because the function
132 // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to
133 // over-write the position of IME windows.
134 *handled = TRUE;
135
136 if (IsTextInputTypeNone())
137 return 0;
138
139 // Reset the composition status and create IME windows.
140 ime_input_.CreateImeWindow(hwnd());
141 ime_input_.ResetComposition(hwnd());
142 return 0;
143 }
144
145 LRESULT InputMethodWin::OnImeComposition(
146 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
147 // We have to prevent WTL from calling ::DefWindowProc() because we do not
148 // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages.
149 *handled = TRUE;
150
151 if (IsTextInputTypeNone())
152 return 0;
153
154 // At first, update the position of the IME window.
155 ime_input_.UpdateImeWindow(hwnd());
156
157 // Retrieve the result string and its attributes of the ongoing composition
158 // and send it to a renderer process.
159 ui::CompositionText composition;
160 if (ime_input_.GetResult(hwnd(), lparam, &composition.text)) {
161 GetTextInputClient()->InsertText(composition.text);
162 ime_input_.ResetComposition(hwnd());
163 // Fall though and try reading the composition string.
164 // Japanese IMEs send a message containing both GCS_RESULTSTR and
165 // GCS_COMPSTR, which means an ongoing composition has been finished
166 // by the start of another composition.
167 }
168 // Retrieve the composition string and its attributes of the ongoing
169 // composition and send it to a renderer process.
170 if (ime_input_.GetComposition(hwnd(), lparam, &composition))
171 GetTextInputClient()->SetCompositionText(composition);
172
173 return 0;
174 }
175
176 LRESULT InputMethodWin::OnImeEndComposition(
177 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
178 // Let WTL call ::DefWindowProc() and release its resources.
179 *handled = FALSE;
180
181 if (IsTextInputTypeNone())
182 return 0;
183
184 if (GetTextInputClient()->HasCompositionText())
185 GetTextInputClient()->ClearCompositionText();
186
187 ime_input_.ResetComposition(hwnd());
188 ime_input_.DestroyImeWindow(hwnd());
189 return 0;
190 }
191
192 LRESULT InputMethodWin::OnChar(
193 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
194 *handled = TRUE;
195
196 // We need to send character events to the focused text input client event if
197 // its text input type is ui::TEXT_INPUT_TYPE_NONE.
198 if (!GetTextInputClient())
199 return 0;
200
201 int flags = 0;
202 flags |= (::GetKeyState(VK_MENU) & 0x80)? ui::EF_ALT_DOWN : 0;
203 flags |= (::GetKeyState(VK_SHIFT) & 0x80)? ui::EF_SHIFT_DOWN : 0;
204 flags |= (::GetKeyState(VK_CONTROL) & 0x80)? ui::EF_CONTROL_DOWN : 0;
205 GetTextInputClient()->InsertChar(static_cast<char16>(wparam), flags);
206 return 0;
207 }
208
209 LRESULT InputMethodWin::OnDeadChar(
210 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
211 *handled = TRUE;
212
213 if (IsTextInputTypeNone())
214 return 0;
215
216 // Shows the dead character as a composition text, so that the user can know
217 // what dead key was pressed.
218 ui::CompositionText composition;
219 composition.text.assign(1, static_cast<char16>(wparam));
220 composition.selection = ui::Range(0, 1);
221 composition.underlines.push_back(
222 ui::CompositionUnderline(0, 1, SK_ColorBLACK, false));
223 GetTextInputClient()->SetCompositionText(composition);
224 return 0;
225 }
226
227 void InputMethodWin::ConfirmCompositionText() {
228 if (!IsTextInputTypeNone()) {
229 ime_input_.CleanupComposition(hwnd());
230 // Though above line should confirm the client's composition text by sending
231 // a result text to us, in case the input method and the client are in
232 // inconsistent states, we check the client's composition state again.
233 if (GetTextInputClient()->HasCompositionText())
234 GetTextInputClient()->ConfirmCompositionText();
235 }
236 }
237
238 void InputMethodWin::UpdateIMEState() {
239 // Use switch here in case we are going to add more text input types.
240 // We disable input method in password field.
241 switch (GetTextInputType()) {
242 case ui::TEXT_INPUT_TYPE_NONE:
243 case ui::TEXT_INPUT_TYPE_PASSWORD:
244 ime_input_.DisableIME(hwnd());
245 break;
246 default:
247 ime_input_.EnableIME(hwnd());
248 break;
249 }
250 }
251
252 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698