OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/controls/textfield/textfield.h" | 5 #include "ui/views/controls/textfield/textfield.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/pickle.h" | 12 #include "base/pickle.h" |
13 #include "base/strings/string16.h" | 13 #include "base/strings/string16.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "ui/accessibility/ax_view_state.h" | 15 #include "ui/accessibility/ax_view_state.h" |
16 #include "ui/base/clipboard/clipboard.h" | 16 #include "ui/base/clipboard/clipboard.h" |
17 #include "ui/base/clipboard/scoped_clipboard_writer.h" | 17 #include "ui/base/clipboard/scoped_clipboard_writer.h" |
18 #include "ui/base/dragdrop/drag_drop_types.h" | 18 #include "ui/base/dragdrop/drag_drop_types.h" |
| 19 #include "ui/base/ime/input_method_base.h" |
| 20 #include "ui/base/ime/input_method_delegate.h" |
| 21 #include "ui/base/ime/input_method_factory.h" |
19 #include "ui/base/ime/text_input_client.h" | 22 #include "ui/base/ime/text_input_client.h" |
20 #include "ui/base/l10n/l10n_util.h" | 23 #include "ui/base/l10n/l10n_util.h" |
21 #include "ui/base/ui_base_switches.h" | 24 #include "ui/base/ui_base_switches.h" |
22 #include "ui/base/ui_base_switches_util.h" | 25 #include "ui/base/ui_base_switches_util.h" |
23 #include "ui/events/event.h" | 26 #include "ui/events/event.h" |
| 27 #include "ui/events/event_processor.h" |
24 #include "ui/events/event_utils.h" | 28 #include "ui/events/event_utils.h" |
25 #include "ui/events/keycodes/keyboard_codes.h" | 29 #include "ui/events/keycodes/keyboard_codes.h" |
26 #include "ui/events/test/event_generator.h" | 30 #include "ui/events/test/event_generator.h" |
27 #include "ui/gfx/render_text.h" | 31 #include "ui/gfx/render_text.h" |
28 #include "ui/strings/grit/ui_strings.h" | 32 #include "ui/strings/grit/ui_strings.h" |
29 #include "ui/views/controls/textfield/textfield_controller.h" | 33 #include "ui/views/controls/textfield/textfield_controller.h" |
30 #include "ui/views/controls/textfield/textfield_model.h" | 34 #include "ui/views/controls/textfield/textfield_model.h" |
31 #include "ui/views/controls/textfield/textfield_test_api.h" | 35 #include "ui/views/controls/textfield/textfield_test_api.h" |
32 #include "ui/views/focus/focus_manager.h" | 36 #include "ui/views/focus/focus_manager.h" |
33 #include "ui/views/ime/mock_input_method.h" | |
34 #include "ui/views/test/test_views_delegate.h" | 37 #include "ui/views/test/test_views_delegate.h" |
35 #include "ui/views/test/views_test_base.h" | 38 #include "ui/views/test/views_test_base.h" |
36 #include "ui/views/test/widget_test.h" | 39 #include "ui/views/test/widget_test.h" |
37 #include "ui/views/widget/widget.h" | 40 #include "ui/views/widget/widget.h" |
38 #include "url/gurl.h" | 41 #include "url/gurl.h" |
39 | 42 |
40 #if defined(OS_WIN) | 43 #if defined(OS_WIN) |
41 #include "base/win/windows_version.h" | 44 #include "base/win/windows_version.h" |
42 #endif | 45 #endif |
43 | 46 |
44 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 47 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
45 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h" | 48 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h" |
46 #endif | 49 #endif |
47 | 50 |
48 #if defined(USE_X11) | 51 #if defined(USE_X11) |
49 #include "ui/events/event_utils.h" | 52 #include "ui/events/event_utils.h" |
50 #endif | 53 #endif |
51 | 54 |
52 using base::ASCIIToUTF16; | 55 using base::ASCIIToUTF16; |
53 using base::UTF8ToUTF16; | 56 using base::UTF8ToUTF16; |
54 using base::WideToUTF16; | 57 using base::WideToUTF16; |
55 | 58 |
56 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) | 59 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) |
57 | 60 |
58 namespace { | 61 namespace { |
59 | 62 |
60 const base::char16 kHebrewLetterSamekh = 0x05E1; | 63 const base::char16 kHebrewLetterSamekh = 0x05E1; |
61 | 64 |
| 65 class MockInputMethod : public ui::InputMethodBase { |
| 66 public: |
| 67 MockInputMethod(); |
| 68 ~MockInputMethod() override; |
| 69 |
| 70 // Overridden from InputMethod: |
| 71 bool OnUntranslatedIMEMessage(const base::NativeEvent& event, |
| 72 NativeEventResult* result) override; |
| 73 bool DispatchKeyEvent(const ui::KeyEvent& key) override; |
| 74 void OnTextInputTypeChanged(const ui::TextInputClient* client) override; |
| 75 void OnCaretBoundsChanged(const ui::TextInputClient* client) override {} |
| 76 void CancelComposition(const ui::TextInputClient* client) override; |
| 77 void OnInputLocaleChanged() override {} |
| 78 std::string GetInputLocale() override; |
| 79 bool IsActive() override; |
| 80 bool IsCandidatePopupOpen() const override; |
| 81 void ShowImeIfNeeded() override {} |
| 82 |
| 83 bool untranslated_ime_message_called() const { |
| 84 return untranslated_ime_message_called_; |
| 85 } |
| 86 bool text_input_type_changed() const { return text_input_type_changed_; } |
| 87 bool cancel_composition_called() const { return cancel_composition_called_; } |
| 88 |
| 89 // Clears all internal states and result. |
| 90 void Clear(); |
| 91 |
| 92 void SetCompositionTextForNextKey(const ui::CompositionText& composition); |
| 93 void SetResultTextForNextKey(const base::string16& result); |
| 94 |
| 95 private: |
| 96 // Overridden from InputMethodBase. |
| 97 void OnWillChangeFocusedClient(ui::TextInputClient* focused_before, |
| 98 ui::TextInputClient* focused) override; |
| 99 |
| 100 // Clears boolean states defined below. |
| 101 void ClearStates(); |
| 102 |
| 103 // Whether a mock composition or result is scheduled for the next key event. |
| 104 bool HasComposition(); |
| 105 |
| 106 // Clears only composition information and result text. |
| 107 void ClearComposition(); |
| 108 |
| 109 // Composition information for the next key event. It'll be cleared |
| 110 // automatically after dispatching the next key event. |
| 111 ui::CompositionText composition_; |
| 112 |
| 113 // Result text for the next key event. It'll be cleared automatically after |
| 114 // dispatching the next key event. |
| 115 base::string16 result_text_; |
| 116 |
| 117 // Record call state of corresponding methods. They will be set to false |
| 118 // automatically before dispatching a key event. |
| 119 bool untranslated_ime_message_called_; |
| 120 bool text_input_type_changed_; |
| 121 bool cancel_composition_called_; |
| 122 |
| 123 DISALLOW_COPY_AND_ASSIGN(MockInputMethod); |
| 124 }; |
| 125 |
| 126 MockInputMethod::MockInputMethod() |
| 127 : untranslated_ime_message_called_(false), |
| 128 text_input_type_changed_(false), |
| 129 cancel_composition_called_(false) { |
| 130 } |
| 131 |
| 132 MockInputMethod::~MockInputMethod() { |
| 133 } |
| 134 |
| 135 bool MockInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent& event, |
| 136 NativeEventResult* result) { |
| 137 if (result) |
| 138 *result = NativeEventResult(); |
| 139 return false; |
| 140 } |
| 141 |
| 142 bool MockInputMethod::DispatchKeyEvent(const ui::KeyEvent& key) { |
| 143 // Checks whether the key event is from EventGenerator on Windows which will |
| 144 // generate key event for WM_CHAR. |
| 145 // The MockInputMethod will insert char on WM_KEYDOWN so ignore WM_CHAR here. |
| 146 if (key.is_char() && key.HasNativeEvent()) |
| 147 return true; |
| 148 |
| 149 bool handled = !IsTextInputTypeNone() && HasComposition(); |
| 150 ClearStates(); |
| 151 if (handled) { |
| 152 DCHECK(!key.is_char()); |
| 153 ui::KeyEvent mock_key(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, key.flags()); |
| 154 DispatchKeyEventPostIME(mock_key); |
| 155 } else { |
| 156 DispatchKeyEventPostIME(key); |
| 157 } |
| 158 |
| 159 ui::TextInputClient* client = GetTextInputClient(); |
| 160 if (client) { |
| 161 if (handled) { |
| 162 if (result_text_.length()) |
| 163 client->InsertText(result_text_); |
| 164 if (composition_.text.length()) |
| 165 client->SetCompositionText(composition_); |
| 166 else |
| 167 client->ClearCompositionText(); |
| 168 } else if (key.type() == ui::ET_KEY_PRESSED) { |
| 169 base::char16 ch = key.GetCharacter(); |
| 170 if (ch) |
| 171 client->InsertChar(ch, key.flags()); |
| 172 } |
| 173 } |
| 174 |
| 175 ClearComposition(); |
| 176 return true; |
| 177 } |
| 178 |
| 179 void MockInputMethod::OnTextInputTypeChanged( |
| 180 const ui::TextInputClient* client) { |
| 181 if (IsTextInputClientFocused(client)) |
| 182 text_input_type_changed_ = true; |
| 183 InputMethodBase::OnTextInputTypeChanged(client); |
| 184 } |
| 185 |
| 186 void MockInputMethod::CancelComposition(const ui::TextInputClient* client) { |
| 187 if (IsTextInputClientFocused(client)) { |
| 188 cancel_composition_called_ = true; |
| 189 ClearComposition(); |
| 190 } |
| 191 } |
| 192 |
| 193 std::string MockInputMethod::GetInputLocale() { |
| 194 return "en-US"; |
| 195 } |
| 196 |
| 197 bool MockInputMethod::IsActive() { |
| 198 return true; |
| 199 } |
| 200 |
| 201 bool MockInputMethod::IsCandidatePopupOpen() const { |
| 202 return false; |
| 203 } |
| 204 |
| 205 void MockInputMethod::OnWillChangeFocusedClient( |
| 206 ui::TextInputClient* focused_before, |
| 207 ui::TextInputClient* focused) { |
| 208 ui::TextInputClient* client = GetTextInputClient(); |
| 209 if (client && client->HasCompositionText()) |
| 210 client->ConfirmCompositionText(); |
| 211 ClearComposition(); |
| 212 } |
| 213 |
| 214 void MockInputMethod::Clear() { |
| 215 ClearStates(); |
| 216 ClearComposition(); |
| 217 } |
| 218 |
| 219 void MockInputMethod::SetCompositionTextForNextKey( |
| 220 const ui::CompositionText& composition) { |
| 221 composition_ = composition; |
| 222 } |
| 223 |
| 224 void MockInputMethod::SetResultTextForNextKey(const base::string16& result) { |
| 225 result_text_ = result; |
| 226 } |
| 227 |
| 228 void MockInputMethod::ClearStates() { |
| 229 untranslated_ime_message_called_ = false; |
| 230 text_input_type_changed_ = false; |
| 231 cancel_composition_called_ = false; |
| 232 } |
| 233 |
| 234 bool MockInputMethod::HasComposition() { |
| 235 return composition_.text.length() || result_text_.length(); |
| 236 } |
| 237 |
| 238 void MockInputMethod::ClearComposition() { |
| 239 composition_.Clear(); |
| 240 result_text_.clear(); |
| 241 } |
| 242 |
62 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults. | 243 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults. |
63 class TestTextfield : public views::Textfield { | 244 class TestTextfield : public views::Textfield { |
64 public: | 245 public: |
65 TestTextfield() | 246 TestTextfield() |
66 : Textfield(), | 247 : Textfield(), |
67 key_handled_(false), | 248 key_handled_(false), |
68 key_received_(false), | 249 key_received_(false), |
69 weak_ptr_factory_(this) {} | 250 weak_ptr_factory_(this) {} |
70 | 251 |
71 bool OnKeyPressed(const ui::KeyEvent& e) override { | 252 bool OnKeyPressed(const ui::KeyEvent& e) override { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 class TextfieldTest : public ViewsTestBase, public TextfieldController { | 345 class TextfieldTest : public ViewsTestBase, public TextfieldController { |
165 public: | 346 public: |
166 TextfieldTest() | 347 TextfieldTest() |
167 : widget_(NULL), | 348 : widget_(NULL), |
168 textfield_(NULL), | 349 textfield_(NULL), |
169 model_(NULL), | 350 model_(NULL), |
170 input_method_(NULL), | 351 input_method_(NULL), |
171 on_before_user_action_(0), | 352 on_before_user_action_(0), |
172 on_after_user_action_(0), | 353 on_after_user_action_(0), |
173 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) { | 354 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) { |
| 355 input_method_ = new MockInputMethod(); |
| 356 ui::SetUpInputMethodForTesting(input_method_); |
174 } | 357 } |
175 | 358 |
176 // ::testing::Test: | 359 // ::testing::Test: |
177 void TearDown() override { | 360 void TearDown() override { |
178 if (widget_) | 361 if (widget_) |
179 widget_->Close(); | 362 widget_->Close(); |
180 ViewsTestBase::TearDown(); | 363 ViewsTestBase::TearDown(); |
181 } | 364 } |
182 | 365 |
183 ui::ClipboardType GetAndResetCopiedToClipboard() { | 366 ui::ClipboardType GetAndResetCopiedToClipboard() { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 textfield_->set_controller(this); | 400 textfield_->set_controller(this); |
218 widget_ = new Widget(); | 401 widget_ = new Widget(); |
219 | 402 |
220 // The widget type must be an activatable type, and we don't want to worry | 403 // The widget type must be an activatable type, and we don't want to worry |
221 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS. | 404 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS. |
222 Widget::InitParams params = | 405 Widget::InitParams params = |
223 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); | 406 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); |
224 | 407 |
225 params.bounds = gfx::Rect(100, 100, 100, 100); | 408 params.bounds = gfx::Rect(100, 100, 100, 100); |
226 widget_->Init(params); | 409 widget_->Init(params); |
| 410 input_method_->SetDelegate( |
| 411 test::WidgetTest::GetInputMethodDelegateForWidget(widget_)); |
227 View* container = new View(); | 412 View* container = new View(); |
228 widget_->SetContentsView(container); | 413 widget_->SetContentsView(container); |
229 container->AddChildView(textfield_); | 414 container->AddChildView(textfield_); |
230 textfield_->SetBoundsRect(params.bounds); | 415 textfield_->SetBoundsRect(params.bounds); |
231 textfield_->set_id(1); | 416 textfield_->set_id(1); |
232 test_api_.reset(new TextfieldTestApi(textfield_)); | 417 test_api_.reset(new TextfieldTestApi(textfield_)); |
233 | 418 |
234 for (int i = 1; i < count; i++) { | 419 for (int i = 1; i < count; i++) { |
235 Textfield* textfield = new Textfield(); | 420 Textfield* textfield = new Textfield(); |
236 container->AddChildView(textfield); | 421 container->AddChildView(textfield); |
237 textfield->set_id(i + 1); | 422 textfield->set_id(i + 1); |
238 } | 423 } |
239 | 424 |
240 model_ = test_api_->model(); | 425 model_ = test_api_->model(); |
241 model_->ClearEditHistory(); | 426 model_->ClearEditHistory(); |
242 | 427 |
243 input_method_ = new MockInputMethod(); | |
244 widget_->ReplaceInputMethod(input_method_); | |
245 | |
246 // Since the window type is activatable, showing the widget will also | 428 // Since the window type is activatable, showing the widget will also |
247 // activate it. Calling Activate directly is insufficient, since that does | 429 // activate it. Calling Activate directly is insufficient, since that does |
248 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the | 430 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the |
249 // widget and the textfield must have focus to properly handle input. | 431 // widget and the textfield must have focus to properly handle input. |
250 widget_->Show(); | 432 widget_->Show(); |
251 textfield_->RequestFocus(); | 433 textfield_->RequestFocus(); |
252 | 434 |
253 // On Mac, activation is asynchronous since desktop widgets are used. We | 435 // On Mac, activation is asynchronous since desktop widgets are used. We |
254 // don't want parallel tests to steal active status either, so fake it. | 436 // don't want parallel tests to steal active status either, so fake it. |
255 #if defined(OS_MACOSX) && !defined(USE_AURA) | 437 #if defined(OS_MACOSX) && !defined(USE_AURA) |
(...skipping 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1276 SendKeyEvent(ui::VKEY_DELETE); | 1458 SendKeyEvent(ui::VKEY_DELETE); |
1277 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); | 1459 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); |
1278 SendKeyEvent(ui::VKEY_BACK); | 1460 SendKeyEvent(ui::VKEY_BACK); |
1279 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); | 1461 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); |
1280 SendKeyEvent(ui::VKEY_T); | 1462 SendKeyEvent(ui::VKEY_T); |
1281 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); | 1463 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); |
1282 } | 1464 } |
1283 | 1465 |
1284 TEST_F(TextfieldTest, TextInputClientTest) { | 1466 TEST_F(TextfieldTest, TextInputClientTest) { |
1285 InitTextfield(); | 1467 InitTextfield(); |
1286 ui::TextInputClient* client = textfield_->GetTextInputClient(); | 1468 ui::TextInputClient* client = textfield_; |
1287 EXPECT_TRUE(client); | 1469 EXPECT_TRUE(client); |
1288 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, client->GetTextInputType()); | 1470 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, client->GetTextInputType()); |
1289 | 1471 |
1290 textfield_->SetText(ASCIIToUTF16("0123456789")); | 1472 textfield_->SetText(ASCIIToUTF16("0123456789")); |
1291 gfx::Range range; | 1473 gfx::Range range; |
1292 EXPECT_TRUE(client->GetTextRange(&range)); | 1474 EXPECT_TRUE(client->GetTextRange(&range)); |
1293 EXPECT_EQ(0U, range.start()); | 1475 EXPECT_EQ(0U, range.start()); |
1294 EXPECT_EQ(10U, range.end()); | 1476 EXPECT_EQ(10U, range.end()); |
1295 | 1477 |
1296 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(1, 4))); | 1478 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(1, 4))); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1373 textfield_->clear(); | 1555 textfield_->clear(); |
1374 textfield_->ClearSelection(); | 1556 textfield_->ClearSelection(); |
1375 textfield_->SelectAll(false); | 1557 textfield_->SelectAll(false); |
1376 EXPECT_EQ(0, on_before_user_action_); | 1558 EXPECT_EQ(0, on_before_user_action_); |
1377 EXPECT_EQ(0, on_after_user_action_); | 1559 EXPECT_EQ(0, on_after_user_action_); |
1378 | 1560 |
1379 input_method_->Clear(); | 1561 input_method_->Clear(); |
1380 | 1562 |
1381 // Changing the Textfield to readonly shouldn't change the input client, since | 1563 // Changing the Textfield to readonly shouldn't change the input client, since |
1382 // it's still required for selections and clipboard copy. | 1564 // it's still required for selections and clipboard copy. |
1383 ui::TextInputClient* text_input_client = textfield_->GetTextInputClient(); | 1565 ui::TextInputClient* text_input_client = textfield_; |
1384 EXPECT_TRUE(text_input_client); | 1566 EXPECT_TRUE(text_input_client); |
1385 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType()); | 1567 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType()); |
1386 textfield_->SetReadOnly(true); | 1568 textfield_->SetReadOnly(true); |
1387 EXPECT_TRUE(input_method_->text_input_type_changed()); | 1569 EXPECT_TRUE(input_method_->text_input_type_changed()); |
1388 EXPECT_EQ(text_input_client, textfield_->GetTextInputClient()); | |
1389 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType()); | 1570 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType()); |
1390 | 1571 |
1391 input_method_->Clear(); | 1572 input_method_->Clear(); |
1392 textfield_->SetReadOnly(false); | 1573 textfield_->SetReadOnly(false); |
1393 EXPECT_TRUE(input_method_->text_input_type_changed()); | 1574 EXPECT_TRUE(input_method_->text_input_type_changed()); |
1394 EXPECT_EQ(text_input_client, textfield_->GetTextInputClient()); | |
1395 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType()); | 1575 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType()); |
1396 | 1576 |
1397 input_method_->Clear(); | 1577 input_method_->Clear(); |
1398 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); | 1578 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
1399 EXPECT_TRUE(input_method_->text_input_type_changed()); | 1579 EXPECT_TRUE(input_method_->text_input_type_changed()); |
1400 EXPECT_TRUE(textfield_->GetTextInputClient()); | |
1401 } | 1580 } |
1402 | 1581 |
1403 TEST_F(TextfieldTest, UndoRedoTest) { | 1582 TEST_F(TextfieldTest, UndoRedoTest) { |
1404 InitTextfield(); | 1583 InitTextfield(); |
1405 SendKeyEvent(ui::VKEY_A); | 1584 SendKeyEvent(ui::VKEY_A); |
1406 EXPECT_STR_EQ("a", textfield_->text()); | 1585 EXPECT_STR_EQ("a", textfield_->text()); |
1407 SendKeyEvent(ui::VKEY_Z, false, true); | 1586 SendKeyEvent(ui::VKEY_Z, false, true); |
1408 EXPECT_STR_EQ("", textfield_->text()); | 1587 EXPECT_STR_EQ("", textfield_->text()); |
1409 SendKeyEvent(ui::VKEY_Z, false, true); | 1588 SendKeyEvent(ui::VKEY_Z, false, true); |
1410 EXPECT_STR_EQ("", textfield_->text()); | 1589 EXPECT_STR_EQ("", textfield_->text()); |
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1901 | 2080 |
1902 // Reset locale. | 2081 // Reset locale. |
1903 base::i18n::SetICUDefaultLocale(locale); | 2082 base::i18n::SetICUDefaultLocale(locale); |
1904 } | 2083 } |
1905 | 2084 |
1906 TEST_F(TextfieldTest, GetCompositionCharacterBoundsTest) { | 2085 TEST_F(TextfieldTest, GetCompositionCharacterBoundsTest) { |
1907 InitTextfield(); | 2086 InitTextfield(); |
1908 ui::CompositionText composition; | 2087 ui::CompositionText composition; |
1909 composition.text = UTF8ToUTF16("abc123"); | 2088 composition.text = UTF8ToUTF16("abc123"); |
1910 const uint32 char_count = static_cast<uint32>(composition.text.length()); | 2089 const uint32 char_count = static_cast<uint32>(composition.text.length()); |
1911 ui::TextInputClient* client = textfield_->GetTextInputClient(); | 2090 ui::TextInputClient* client = textfield_; |
1912 | 2091 |
1913 // Compare the composition character bounds with surrounding cursor bounds. | 2092 // Compare the composition character bounds with surrounding cursor bounds. |
1914 for (uint32 i = 0; i < char_count; ++i) { | 2093 for (uint32 i = 0; i < char_count; ++i) { |
1915 composition.selection = gfx::Range(i); | 2094 composition.selection = gfx::Range(i); |
1916 client->SetCompositionText(composition); | 2095 client->SetCompositionText(composition); |
1917 gfx::Point cursor_origin = GetCursorBounds().origin(); | 2096 gfx::Point cursor_origin = GetCursorBounds().origin(); |
1918 views::View::ConvertPointToScreen(textfield_, &cursor_origin); | 2097 views::View::ConvertPointToScreen(textfield_, &cursor_origin); |
1919 | 2098 |
1920 composition.selection = gfx::Range(i + 1); | 2099 composition.selection = gfx::Range(i + 1); |
1921 client->SetCompositionText(composition); | 2100 client->SetCompositionText(composition); |
(...skipping 25 matching lines...) Expand all Loading... |
1947 0x5642, 0xDB40, 0xDD00, | 2126 0x5642, 0xDB40, 0xDD00, |
1948 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences | 2127 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences |
1949 0x260E, 0xFE0F, | 2128 0x260E, 0xFE0F, |
1950 // U+0020 SPACE | 2129 // U+0020 SPACE |
1951 0x0020, | 2130 0x0020, |
1952 }; | 2131 }; |
1953 const size_t kUtf16CharsCount = arraysize(kUtf16Chars); | 2132 const size_t kUtf16CharsCount = arraysize(kUtf16Chars); |
1954 | 2133 |
1955 ui::CompositionText composition; | 2134 ui::CompositionText composition; |
1956 composition.text.assign(kUtf16Chars, kUtf16Chars + kUtf16CharsCount); | 2135 composition.text.assign(kUtf16Chars, kUtf16Chars + kUtf16CharsCount); |
1957 ui::TextInputClient* client = textfield_->GetTextInputClient(); | 2136 ui::TextInputClient* client = textfield_; |
1958 client->SetCompositionText(composition); | 2137 client->SetCompositionText(composition); |
1959 | 2138 |
1960 // Make sure GetCompositionCharacterBounds never fails for index. | 2139 // Make sure GetCompositionCharacterBounds never fails for index. |
1961 gfx::Rect rects[kUtf16CharsCount]; | 2140 gfx::Rect rects[kUtf16CharsCount]; |
1962 gfx::Rect prev_cursor = GetCursorBounds(); | 2141 gfx::Rect prev_cursor = GetCursorBounds(); |
1963 for (uint32 i = 0; i < kUtf16CharsCount; ++i) | 2142 for (uint32 i = 0; i < kUtf16CharsCount; ++i) |
1964 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &rects[i])); | 2143 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &rects[i])); |
1965 | 2144 |
1966 // Here we might expect the following results but it actually depends on how | 2145 // Here we might expect the following results but it actually depends on how |
1967 // Uniscribe or HarfBuzz treats them with given font. | 2146 // Uniscribe or HarfBuzz treats them with given font. |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2358 | 2537 |
2359 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); | 2538 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
2360 ui::AXViewState state_protected; | 2539 ui::AXViewState state_protected; |
2361 textfield_->GetAccessibleState(&state_protected); | 2540 textfield_->GetAccessibleState(&state_protected); |
2362 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD, state_protected.role); | 2541 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD, state_protected.role); |
2363 EXPECT_EQ(ASCIIToUTF16("********"), state_protected.value); | 2542 EXPECT_EQ(ASCIIToUTF16("********"), state_protected.value); |
2364 EXPECT_TRUE(state_protected.HasStateFlag(ui::AX_STATE_PROTECTED)); | 2543 EXPECT_TRUE(state_protected.HasStateFlag(ui::AX_STATE_PROTECTED)); |
2365 } | 2544 } |
2366 | 2545 |
2367 } // namespace views | 2546 } // namespace views |
OLD | NEW |