OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ui/views/controls/textfield/native_textfield_views.h" | |
6 | |
7 #include <set> | |
8 #include <string> | |
9 #include <vector> | |
10 | |
11 #include "base/auto_reset.h" | |
12 #include "base/bind.h" | |
13 #include "base/bind_helpers.h" | |
14 #include "base/callback.h" | |
15 #include "base/command_line.h" | |
16 #include "base/message_loop/message_loop.h" | |
17 #include "base/pickle.h" | |
18 #include "base/strings/string16.h" | |
19 #include "base/strings/utf_string_conversions.h" | |
20 #include "grit/ui_strings.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 #include "ui/base/clipboard/clipboard.h" | |
23 #include "ui/base/clipboard/scoped_clipboard_writer.h" | |
24 #include "ui/base/dragdrop/drag_drop_types.h" | |
25 #include "ui/base/ime/text_input_client.h" | |
26 #include "ui/base/l10n/l10n_util.h" | |
27 #include "ui/base/ui_base_switches.h" | |
28 #include "ui/events/event.h" | |
29 #include "ui/events/keycodes/keyboard_codes.h" | |
30 #include "ui/gfx/render_text.h" | |
31 #include "ui/views/controls/textfield/textfield.h" | |
32 #include "ui/views/controls/textfield/textfield_controller.h" | |
33 #include "ui/views/controls/textfield/textfield_views_model.h" | |
34 #include "ui/views/focus/focus_manager.h" | |
35 #include "ui/views/ime/mock_input_method.h" | |
36 #include "ui/views/test/test_views_delegate.h" | |
37 #include "ui/views/test/views_test_base.h" | |
38 #include "ui/views/widget/native_widget_private.h" | |
39 #include "ui/views/widget/widget.h" | |
40 #include "url/gurl.h" | |
41 | |
42 #if defined(OS_WIN) | |
43 #include "base/win/windows_version.h" | |
44 #endif | |
45 | |
46 using base::ASCIIToUTF16; | |
47 using base::UTF8ToUTF16; | |
48 using base::WideToUTF16; | |
49 | |
50 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) | |
51 | |
52 namespace { | |
53 | |
54 const base::char16 kHebrewLetterSamekh = 0x05E1; | |
55 | |
56 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults. | |
57 class TestTextfield : public views::Textfield { | |
58 public: | |
59 explicit TestTextfield(StyleFlags style) | |
60 : Textfield(style), | |
61 key_handled_(false), | |
62 key_received_(false) { | |
63 } | |
64 | |
65 virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE { | |
66 key_received_ = true; | |
67 key_handled_ = views::Textfield::OnKeyPressed(e); | |
68 return key_handled_; | |
69 } | |
70 | |
71 virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE { | |
72 key_received_ = true; | |
73 key_handled_ = views::Textfield::OnKeyReleased(e); | |
74 return key_handled_; | |
75 } | |
76 | |
77 bool key_handled() const { return key_handled_; } | |
78 bool key_received() const { return key_received_; } | |
79 | |
80 void clear() { key_received_ = key_handled_ = false; } | |
81 | |
82 bool focusable() const { return View::focusable(); } | |
83 | |
84 private: | |
85 bool key_handled_; | |
86 bool key_received_; | |
87 | |
88 DISALLOW_COPY_AND_ASSIGN(TestTextfield); | |
89 }; | |
90 | |
91 // A helper class for use with ui::TextInputClient::GetTextFromRange(). | |
92 class GetTextHelper { | |
93 public: | |
94 GetTextHelper() {} | |
95 | |
96 void set_text(const base::string16& text) { text_ = text; } | |
97 const base::string16& text() const { return text_; } | |
98 | |
99 private: | |
100 base::string16 text_; | |
101 | |
102 DISALLOW_COPY_AND_ASSIGN(GetTextHelper); | |
103 }; | |
104 | |
105 // Convenience to make constructing a GestureEvent simpler. | |
106 class GestureEventForTest : public ui::GestureEvent { | |
107 public: | |
108 GestureEventForTest(ui::EventType type, int x, int y, float delta_x, | |
109 float delta_y) | |
110 : GestureEvent(type, x, y, 0, base::TimeDelta(), | |
111 ui::GestureEventDetails(type, delta_x, delta_y), 0) { | |
112 } | |
113 | |
114 private: | |
115 DISALLOW_COPY_AND_ASSIGN(GestureEventForTest); | |
116 }; | |
117 | |
118 } // namespace | |
119 | |
120 namespace views { | |
121 | |
122 // TODO(oshima): Move tests that are independent of TextfieldViews to | |
123 // textfield_unittests.cc once we move the test utility functions | |
124 // from chrome/browser/automation/ to ui/base/test/. | |
125 class NativeTextfieldViewsTest : public ViewsTestBase, | |
126 public TextfieldController { | |
127 public: | |
128 NativeTextfieldViewsTest() | |
129 : widget_(NULL), | |
130 textfield_(NULL), | |
131 textfield_view_(NULL), | |
132 model_(NULL), | |
133 input_method_(NULL), | |
134 on_before_user_action_(0), | |
135 on_after_user_action_(0) { | |
136 } | |
137 | |
138 // ::testing::Test: | |
139 virtual void SetUp() { | |
140 ViewsTestBase::SetUp(); | |
141 } | |
142 | |
143 virtual void TearDown() { | |
144 if (widget_) | |
145 widget_->Close(); | |
146 ViewsTestBase::TearDown(); | |
147 } | |
148 | |
149 // TextfieldController: | |
150 virtual void ContentsChanged(Textfield* sender, | |
151 const base::string16& new_contents) OVERRIDE { | |
152 // Paste calls TextfieldController::ContentsChanged() explicitly even if the | |
153 // paste action did not change the content. So |new_contents| may match | |
154 // |last_contents_|. For more info, see http://crbug.com/79002 | |
155 last_contents_ = new_contents; | |
156 } | |
157 | |
158 virtual bool HandleKeyEvent(Textfield* sender, | |
159 const ui::KeyEvent& key_event) OVERRIDE { | |
160 // TODO(oshima): figure out how to test the keystroke. | |
161 return false; | |
162 } | |
163 | |
164 virtual void OnBeforeUserAction(Textfield* sender) OVERRIDE { | |
165 ++on_before_user_action_; | |
166 } | |
167 | |
168 virtual void OnAfterUserAction(Textfield* sender) OVERRIDE { | |
169 ++on_after_user_action_; | |
170 } | |
171 | |
172 void InitTextfield(Textfield::StyleFlags style) { | |
173 InitTextfields(style, 1); | |
174 } | |
175 | |
176 void InitTextfields(Textfield::StyleFlags style, int count) { | |
177 ASSERT_FALSE(textfield_); | |
178 textfield_ = new TestTextfield(style); | |
179 textfield_->SetController(this); | |
180 widget_ = new Widget(); | |
181 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | |
182 params.bounds = gfx::Rect(100, 100, 100, 100); | |
183 widget_->Init(params); | |
184 View* container = new View(); | |
185 widget_->SetContentsView(container); | |
186 container->AddChildView(textfield_); | |
187 | |
188 textfield_view_ = textfield_->GetTextfieldViewForTesting(); | |
189 DCHECK(textfield_view_); | |
190 textfield_view_->SetBoundsRect(params.bounds); | |
191 textfield_->set_id(1); | |
192 | |
193 for (int i = 1; i < count; i++) { | |
194 Textfield* textfield = new Textfield(style); | |
195 container->AddChildView(textfield); | |
196 textfield->set_id(i + 1); | |
197 } | |
198 | |
199 model_ = textfield_view_->model_.get(); | |
200 model_->ClearEditHistory(); | |
201 | |
202 input_method_ = new MockInputMethod(); | |
203 widget_->ReplaceInputMethod(input_method_); | |
204 | |
205 // Activate the widget and focus the textfield for input handling. | |
206 widget_->Activate(); | |
207 textfield_->RequestFocus(); | |
208 } | |
209 | |
210 ui::MenuModel* GetContextMenuModel() { | |
211 textfield_view_->UpdateContextMenu(); | |
212 return textfield_view_->context_menu_contents_.get(); | |
213 } | |
214 | |
215 ui::TouchSelectionController* GetTouchSelectionController() { | |
216 return textfield_view_->touch_selection_controller_.get(); | |
217 } | |
218 | |
219 protected: | |
220 void SendKeyEvent(ui::KeyboardCode key_code, | |
221 bool alt, | |
222 bool shift, | |
223 bool control, | |
224 bool caps_lock) { | |
225 int flags = (alt ? ui::EF_ALT_DOWN : 0) | | |
226 (shift ? ui::EF_SHIFT_DOWN : 0) | | |
227 (control ? ui::EF_CONTROL_DOWN : 0) | | |
228 (caps_lock ? ui::EF_CAPS_LOCK_DOWN : 0); | |
229 ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, flags, false); | |
230 input_method_->DispatchKeyEvent(event); | |
231 } | |
232 | |
233 void SendKeyEvent(ui::KeyboardCode key_code, bool shift, bool control) { | |
234 SendKeyEvent(key_code, false, shift, control, false); | |
235 } | |
236 | |
237 void SendKeyEvent(ui::KeyboardCode key_code) { | |
238 SendKeyEvent(key_code, false, false); | |
239 } | |
240 | |
241 void SendKeyEvent(base::char16 ch) { | |
242 if (ch < 0x80) { | |
243 ui::KeyboardCode code = | |
244 ch == ' ' ? ui::VKEY_SPACE : | |
245 static_cast<ui::KeyboardCode>(ui::VKEY_A + ch - 'a'); | |
246 SendKeyEvent(code); | |
247 } else { | |
248 ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, 0, false); | |
249 event.set_character(ch); | |
250 input_method_->DispatchKeyEvent(event); | |
251 } | |
252 } | |
253 | |
254 base::string16 GetClipboardText() const { | |
255 base::string16 text; | |
256 ui::Clipboard::GetForCurrentThread()-> | |
257 ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &text); | |
258 return text; | |
259 } | |
260 | |
261 void SetClipboardText(const std::string& text) { | |
262 ui::ScopedClipboardWriter clipboard_writer( | |
263 ui::Clipboard::GetForCurrentThread(), | |
264 ui::CLIPBOARD_TYPE_COPY_PASTE); | |
265 clipboard_writer.WriteText(ASCIIToUTF16(text)); | |
266 } | |
267 | |
268 View* GetFocusedView() { | |
269 return widget_->GetFocusManager()->GetFocusedView(); | |
270 } | |
271 | |
272 int GetCursorPositionX(int cursor_pos) { | |
273 gfx::RenderText* render_text = textfield_view_->GetRenderText(); | |
274 return render_text->GetCursorBounds( | |
275 gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), false).x(); | |
276 } | |
277 | |
278 // Get the current cursor bounds. | |
279 gfx::Rect GetCursorBounds() { | |
280 gfx::RenderText* render_text = textfield_view_->GetRenderText(); | |
281 gfx::Rect bounds = render_text->GetUpdatedCursorBounds(); | |
282 return bounds; | |
283 } | |
284 | |
285 // Get the cursor bounds of |sel|. | |
286 gfx::Rect GetCursorBounds(const gfx::SelectionModel& sel) { | |
287 gfx::RenderText* render_text = textfield_view_->GetRenderText(); | |
288 gfx::Rect bounds = render_text->GetCursorBounds(sel, true); | |
289 return bounds; | |
290 } | |
291 | |
292 gfx::Rect GetDisplayRect() { | |
293 return textfield_view_->GetRenderText()->display_rect(); | |
294 } | |
295 | |
296 // Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and | |
297 // y-axis is in the middle of |bound|'s vertical range. | |
298 void MouseClick(const gfx::Rect bound, int x_offset) { | |
299 gfx::Point point(bound.x() + x_offset, bound.y() + bound.height() / 2); | |
300 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point, | |
301 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
302 textfield_view_->OnMousePressed(click); | |
303 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point, point, | |
304 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
305 textfield_view_->OnMouseReleased(release); | |
306 } | |
307 | |
308 // This is to avoid double/triple click. | |
309 void NonClientMouseClick() { | |
310 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), | |
311 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT, | |
312 ui::EF_LEFT_MOUSE_BUTTON); | |
313 textfield_view_->OnMousePressed(click); | |
314 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), | |
315 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT, | |
316 ui::EF_LEFT_MOUSE_BUTTON); | |
317 textfield_view_->OnMouseReleased(release); | |
318 } | |
319 | |
320 // Wrap for visibility in test classes. | |
321 ui::TextInputType GetTextInputType() { | |
322 return textfield_view_->GetTextInputType(); | |
323 } | |
324 | |
325 void VerifyTextfieldContextMenuContents(bool textfield_has_selection, | |
326 bool can_undo, | |
327 ui::MenuModel* menu) { | |
328 EXPECT_EQ(can_undo, menu->IsEnabledAt(0 /* UNDO */)); | |
329 EXPECT_TRUE(menu->IsEnabledAt(1 /* Separator */)); | |
330 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(2 /* CUT */)); | |
331 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(3 /* COPY */)); | |
332 EXPECT_NE(GetClipboardText().empty(), menu->IsEnabledAt(4 /* PASTE */)); | |
333 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(5 /* DELETE */)); | |
334 EXPECT_TRUE(menu->IsEnabledAt(6 /* Separator */)); | |
335 EXPECT_TRUE(menu->IsEnabledAt(7 /* SELECT ALL */)); | |
336 } | |
337 | |
338 // We need widget to populate wrapper class. | |
339 Widget* widget_; | |
340 | |
341 TestTextfield* textfield_; | |
342 NativeTextfieldViews* textfield_view_; | |
343 TextfieldViewsModel* model_; | |
344 | |
345 // The string from Controller::ContentsChanged callback. | |
346 base::string16 last_contents_; | |
347 | |
348 // For testing input method related behaviors. | |
349 MockInputMethod* input_method_; | |
350 | |
351 // Indicates how many times OnBeforeUserAction() is called. | |
352 int on_before_user_action_; | |
353 | |
354 // Indicates how many times OnAfterUserAction() is called. | |
355 int on_after_user_action_; | |
356 | |
357 private: | |
358 DISALLOW_COPY_AND_ASSIGN(NativeTextfieldViewsTest); | |
359 }; | |
360 | |
361 TEST_F(NativeTextfieldViewsTest, ModelChangesTest) { | |
362 InitTextfield(Textfield::STYLE_DEFAULT); | |
363 | |
364 // TextfieldController::ContentsChanged() shouldn't be called when changing | |
365 // text programmatically. | |
366 last_contents_.clear(); | |
367 textfield_->SetText(ASCIIToUTF16("this is")); | |
368 | |
369 EXPECT_STR_EQ("this is", model_->GetText()); | |
370 EXPECT_STR_EQ("this is", textfield_->text()); | |
371 EXPECT_TRUE(last_contents_.empty()); | |
372 | |
373 textfield_->AppendText(ASCIIToUTF16(" a test")); | |
374 EXPECT_STR_EQ("this is a test", model_->GetText()); | |
375 EXPECT_STR_EQ("this is a test", textfield_->text()); | |
376 EXPECT_TRUE(last_contents_.empty()); | |
377 | |
378 EXPECT_EQ(base::string16(), textfield_->GetSelectedText()); | |
379 textfield_->SelectAll(false); | |
380 EXPECT_STR_EQ("this is a test", textfield_->GetSelectedText()); | |
381 EXPECT_TRUE(last_contents_.empty()); | |
382 } | |
383 | |
384 TEST_F(NativeTextfieldViewsTest, ModelChangesTestLowerCase) { | |
385 // Check if |model_|'s text is properly lowercased for STYLE_LOWERCASE. | |
386 InitTextfield(Textfield::STYLE_LOWERCASE); | |
387 EXPECT_EQ(0U, textfield_->GetCursorPosition()); | |
388 | |
389 last_contents_.clear(); | |
390 textfield_->SetText(ASCIIToUTF16("THIS IS")); | |
391 EXPECT_EQ(7U, textfield_->GetCursorPosition()); | |
392 | |
393 EXPECT_STR_EQ("this is", model_->GetText()); | |
394 EXPECT_STR_EQ("THIS IS", textfield_->text()); | |
395 EXPECT_TRUE(last_contents_.empty()); | |
396 | |
397 textfield_->AppendText(ASCIIToUTF16(" A TEST")); | |
398 EXPECT_EQ(7U, textfield_->GetCursorPosition()); | |
399 EXPECT_STR_EQ("this is a test", model_->GetText()); | |
400 EXPECT_STR_EQ("THIS IS A TEST", textfield_->text()); | |
401 | |
402 EXPECT_TRUE(last_contents_.empty()); | |
403 } | |
404 | |
405 TEST_F(NativeTextfieldViewsTest, ModelChangesTestLowerCaseI18n) { | |
406 // Check if lower case conversion works for non-ASCII characters. | |
407 InitTextfield(Textfield::STYLE_LOWERCASE); | |
408 EXPECT_EQ(0U, textfield_->GetCursorPosition()); | |
409 | |
410 last_contents_.clear(); | |
411 // Zenkaku Japanese "ABCabc" | |
412 textfield_->SetText(WideToUTF16(L"\xFF21\xFF22\xFF23\xFF41\xFF42\xFF43")); | |
413 EXPECT_EQ(6U, textfield_->GetCursorPosition()); | |
414 // Zenkaku Japanese "abcabc" | |
415 EXPECT_EQ(WideToUTF16(L"\xFF41\xFF42\xFF43\xFF41\xFF42\xFF43"), | |
416 model_->GetText()); | |
417 // Zenkaku Japanese "ABCabc" | |
418 EXPECT_EQ(WideToUTF16(L"\xFF21\xFF22\xFF23\xFF41\xFF42\xFF43"), | |
419 textfield_->text()); | |
420 EXPECT_TRUE(last_contents_.empty()); | |
421 | |
422 // Zenkaku Japanese "XYZxyz" | |
423 textfield_->AppendText(WideToUTF16(L"\xFF38\xFF39\xFF3A\xFF58\xFF59\xFF5A")); | |
424 EXPECT_EQ(6U, textfield_->GetCursorPosition()); | |
425 // Zenkaku Japanese "abcabcxyzxyz" | |
426 EXPECT_EQ(WideToUTF16(L"\xFF41\xFF42\xFF43\xFF41\xFF42\xFF43" | |
427 L"\xFF58\xFF59\xFF5A\xFF58\xFF59\xFF5A"), | |
428 model_->GetText()); | |
429 // Zenkaku Japanese "ABCabcXYZxyz" | |
430 EXPECT_EQ(WideToUTF16(L"\xFF21\xFF22\xFF23\xFF41\xFF42\xFF43" | |
431 L"\xFF38\xFF39\xFF3A\xFF58\xFF59\xFF5A"), | |
432 textfield_->text()); | |
433 EXPECT_TRUE(last_contents_.empty()); | |
434 } | |
435 | |
436 TEST_F(NativeTextfieldViewsTest, ModelChangesTestLowerCaseWithLocale) { | |
437 // Check if lower case conversion honors locale properly. | |
438 std::string locale = l10n_util::GetApplicationLocale(""); | |
439 base::i18n::SetICUDefaultLocale("tr"); | |
440 | |
441 InitTextfield(Textfield::STYLE_LOWERCASE); | |
442 EXPECT_EQ(0U, textfield_->GetCursorPosition()); | |
443 | |
444 last_contents_.clear(); | |
445 // Turkish 'I' should be converted to dotless 'i' (U+0131). | |
446 textfield_->SetText(WideToUTF16(L"I")); | |
447 EXPECT_EQ(1U, textfield_->GetCursorPosition()); | |
448 EXPECT_EQ(WideToUTF16(L"\x0131"), model_->GetText()); | |
449 EXPECT_EQ(WideToUTF16(L"I"), textfield_->text()); | |
450 EXPECT_TRUE(last_contents_.empty()); | |
451 | |
452 base::i18n::SetICUDefaultLocale(locale); | |
453 | |
454 // On default (en) locale, 'I' should be converted to 'i'. | |
455 textfield_->SetText(WideToUTF16(L"I")); | |
456 EXPECT_EQ(1U, textfield_->GetCursorPosition()); | |
457 EXPECT_EQ(WideToUTF16(L"i"), model_->GetText()); | |
458 EXPECT_EQ(WideToUTF16(L"I"), textfield_->text()); | |
459 EXPECT_TRUE(last_contents_.empty()); | |
460 } | |
461 | |
462 TEST_F(NativeTextfieldViewsTest, KeyTest) { | |
463 InitTextfield(Textfield::STYLE_DEFAULT); | |
464 // Event flags: key, alt, shift, ctrl, caps-lock. | |
465 SendKeyEvent(ui::VKEY_T, false, true, false, false); | |
466 SendKeyEvent(ui::VKEY_E, false, false, false, false); | |
467 SendKeyEvent(ui::VKEY_X, false, true, false, true); | |
468 SendKeyEvent(ui::VKEY_T, false, false, false, true); | |
469 SendKeyEvent(ui::VKEY_1, false, true, false, false); | |
470 SendKeyEvent(ui::VKEY_1, false, false, false, false); | |
471 SendKeyEvent(ui::VKEY_1, false, true, false, true); | |
472 SendKeyEvent(ui::VKEY_1, false, false, false, true); | |
473 EXPECT_STR_EQ("TexT!1!1", textfield_->text()); | |
474 } | |
475 | |
476 TEST_F(NativeTextfieldViewsTest, ControlAndSelectTest) { | |
477 // Insert a test string in a textfield. | |
478 InitTextfield(Textfield::STYLE_DEFAULT); | |
479 textfield_->SetText(ASCIIToUTF16("one two three")); | |
480 SendKeyEvent(ui::VKEY_HOME, false /* shift */, false /* control */); | |
481 SendKeyEvent(ui::VKEY_RIGHT, true, false); | |
482 SendKeyEvent(ui::VKEY_RIGHT, true, false); | |
483 SendKeyEvent(ui::VKEY_RIGHT, true, false); | |
484 | |
485 EXPECT_STR_EQ("one", textfield_->GetSelectedText()); | |
486 | |
487 // Test word select. | |
488 SendKeyEvent(ui::VKEY_RIGHT, true, true); | |
489 EXPECT_STR_EQ("one two", textfield_->GetSelectedText()); | |
490 SendKeyEvent(ui::VKEY_RIGHT, true, true); | |
491 EXPECT_STR_EQ("one two three", textfield_->GetSelectedText()); | |
492 SendKeyEvent(ui::VKEY_LEFT, true, true); | |
493 EXPECT_STR_EQ("one two ", textfield_->GetSelectedText()); | |
494 SendKeyEvent(ui::VKEY_LEFT, true, true); | |
495 EXPECT_STR_EQ("one ", textfield_->GetSelectedText()); | |
496 | |
497 // Replace the selected text. | |
498 SendKeyEvent(ui::VKEY_Z, true, false); | |
499 SendKeyEvent(ui::VKEY_E, true, false); | |
500 SendKeyEvent(ui::VKEY_R, true, false); | |
501 SendKeyEvent(ui::VKEY_O, true, false); | |
502 SendKeyEvent(ui::VKEY_SPACE, false, false); | |
503 EXPECT_STR_EQ("ZERO two three", textfield_->text()); | |
504 | |
505 SendKeyEvent(ui::VKEY_END, true, false); | |
506 EXPECT_STR_EQ("two three", textfield_->GetSelectedText()); | |
507 SendKeyEvent(ui::VKEY_HOME, true, false); | |
508 EXPECT_STR_EQ("ZERO ", textfield_->GetSelectedText()); | |
509 } | |
510 | |
511 TEST_F(NativeTextfieldViewsTest, InsertionDeletionTest) { | |
512 // Insert a test string in a textfield. | |
513 InitTextfield(Textfield::STYLE_DEFAULT); | |
514 for (size_t i = 0; i < 10; i++) | |
515 SendKeyEvent(static_cast<ui::KeyboardCode>(ui::VKEY_A + i)); | |
516 EXPECT_STR_EQ("abcdefghij", textfield_->text()); | |
517 | |
518 // Test the delete and backspace keys. | |
519 textfield_->SelectRange(gfx::Range(5)); | |
520 for (int i = 0; i < 3; i++) | |
521 SendKeyEvent(ui::VKEY_BACK); | |
522 EXPECT_STR_EQ("abfghij", textfield_->text()); | |
523 for (int i = 0; i < 3; i++) | |
524 SendKeyEvent(ui::VKEY_DELETE); | |
525 EXPECT_STR_EQ("abij", textfield_->text()); | |
526 | |
527 // Select all and replace with "k". | |
528 textfield_->SelectAll(false); | |
529 SendKeyEvent(ui::VKEY_K); | |
530 EXPECT_STR_EQ("k", textfield_->text()); | |
531 | |
532 // Delete the previous word from cursor. | |
533 textfield_->SetText(ASCIIToUTF16("one two three four")); | |
534 SendKeyEvent(ui::VKEY_END); | |
535 SendKeyEvent(ui::VKEY_BACK, false, false, true, false); | |
536 EXPECT_STR_EQ("one two three ", textfield_->text()); | |
537 | |
538 // Delete text preceeding the cursor in chromeos, do nothing in windows. | |
539 SendKeyEvent(ui::VKEY_LEFT, false, false, true, false); | |
540 SendKeyEvent(ui::VKEY_BACK, false, true, true, false); | |
541 #if defined(OS_WIN) | |
542 EXPECT_STR_EQ("one two three ", textfield_->text()); | |
543 #else | |
544 EXPECT_STR_EQ("three ", textfield_->text()); | |
545 #endif | |
546 | |
547 // Delete the next word from cursor. | |
548 textfield_->SetText(ASCIIToUTF16("one two three four")); | |
549 SendKeyEvent(ui::VKEY_HOME); | |
550 SendKeyEvent(ui::VKEY_DELETE, false, false, true, false); | |
551 EXPECT_STR_EQ(" two three four", textfield_->text()); | |
552 | |
553 // Delete text following the cursor in chromeos, do nothing in windows. | |
554 SendKeyEvent(ui::VKEY_RIGHT, false, false, true, false); | |
555 SendKeyEvent(ui::VKEY_DELETE, false, true, true, false); | |
556 #if defined(OS_WIN) | |
557 EXPECT_STR_EQ(" two three four", textfield_->text()); | |
558 #else | |
559 EXPECT_STR_EQ(" two", textfield_->text()); | |
560 #endif | |
561 } | |
562 | |
563 TEST_F(NativeTextfieldViewsTest, PasswordTest) { | |
564 InitTextfield(Textfield::STYLE_OBSCURED); | |
565 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType()); | |
566 EXPECT_TRUE(textfield_->enabled()); | |
567 EXPECT_TRUE(textfield_->focusable()); | |
568 | |
569 last_contents_.clear(); | |
570 textfield_->SetText(ASCIIToUTF16("password")); | |
571 // Ensure text() and the callback returns the actual text instead of "*". | |
572 EXPECT_STR_EQ("password", textfield_->text()); | |
573 EXPECT_TRUE(last_contents_.empty()); | |
574 model_->SelectAll(false); | |
575 SetClipboardText("foo"); | |
576 | |
577 // Cut and copy should be disabled. | |
578 EXPECT_FALSE(textfield_view_->IsCommandIdEnabled(IDS_APP_CUT)); | |
579 textfield_view_->ExecuteCommand(IDS_APP_CUT, 0); | |
580 SendKeyEvent(ui::VKEY_X, false, true); | |
581 EXPECT_FALSE(textfield_view_->IsCommandIdEnabled(IDS_APP_COPY)); | |
582 textfield_view_->ExecuteCommand(IDS_APP_COPY, 0); | |
583 SendKeyEvent(ui::VKEY_C, false, true); | |
584 SendKeyEvent(ui::VKEY_INSERT, false, true); | |
585 EXPECT_STR_EQ("foo", base::string16(GetClipboardText())); | |
586 EXPECT_STR_EQ("password", textfield_->text()); | |
587 // [Shift]+[Delete] should just delete without copying text to the clipboard. | |
588 textfield_->SelectAll(false); | |
589 SendKeyEvent(ui::VKEY_DELETE, true, false); | |
590 | |
591 // Paste should work normally. | |
592 EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_PASTE)); | |
593 textfield_view_->ExecuteCommand(IDS_APP_PASTE, 0); | |
594 SendKeyEvent(ui::VKEY_V, false, true); | |
595 SendKeyEvent(ui::VKEY_INSERT, true, false); | |
596 EXPECT_STR_EQ("foo", base::string16(GetClipboardText())); | |
597 EXPECT_STR_EQ("foofoofoo", textfield_->text()); | |
598 } | |
599 | |
600 TEST_F(NativeTextfieldViewsTest, InputTypeSetsObscured) { | |
601 InitTextfield(Textfield::STYLE_DEFAULT); | |
602 | |
603 // Defaults to TEXT | |
604 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType()); | |
605 | |
606 // Setting to TEXT_INPUT_TYPE_PASSWORD also sets obscured state of textfield. | |
607 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); | |
608 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType()); | |
609 EXPECT_TRUE(textfield_->IsObscured()); | |
610 } | |
611 | |
612 TEST_F(NativeTextfieldViewsTest, ObscuredSetsInputType) { | |
613 InitTextfield(Textfield::STYLE_DEFAULT); | |
614 | |
615 // Defaults to TEXT | |
616 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType()); | |
617 | |
618 textfield_->SetObscured(true); | |
619 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType()); | |
620 | |
621 textfield_->SetObscured(false); | |
622 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType()); | |
623 } | |
624 | |
625 TEST_F(NativeTextfieldViewsTest, TextInputType) { | |
626 InitTextfield(Textfield::STYLE_DEFAULT); | |
627 | |
628 // Defaults to TEXT | |
629 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType()); | |
630 | |
631 // And can be set. | |
632 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_URL); | |
633 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, GetTextInputType()); | |
634 | |
635 // Readonly textfields have type NONE | |
636 textfield_->SetReadOnly(true); | |
637 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, GetTextInputType()); | |
638 | |
639 textfield_->SetReadOnly(false); | |
640 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, GetTextInputType()); | |
641 | |
642 // As do disabled textfields | |
643 textfield_->SetEnabled(false); | |
644 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, GetTextInputType()); | |
645 } | |
646 | |
647 TEST_F(NativeTextfieldViewsTest, OnKeyPressReturnValueTest) { | |
648 InitTextfield(Textfield::STYLE_DEFAULT); | |
649 | |
650 // Character keys will be handled by input method. | |
651 SendKeyEvent(ui::VKEY_A); | |
652 EXPECT_TRUE(textfield_->key_received()); | |
653 EXPECT_FALSE(textfield_->key_handled()); | |
654 textfield_->clear(); | |
655 | |
656 // Home will be handled. | |
657 SendKeyEvent(ui::VKEY_HOME); | |
658 EXPECT_TRUE(textfield_->key_received()); | |
659 EXPECT_TRUE(textfield_->key_handled()); | |
660 textfield_->clear(); | |
661 | |
662 // F24, up/down key won't be handled. | |
663 SendKeyEvent(ui::VKEY_F24); | |
664 EXPECT_TRUE(textfield_->key_received()); | |
665 EXPECT_FALSE(textfield_->key_handled()); | |
666 textfield_->clear(); | |
667 | |
668 SendKeyEvent(ui::VKEY_UP); | |
669 EXPECT_TRUE(textfield_->key_received()); | |
670 EXPECT_FALSE(textfield_->key_handled()); | |
671 textfield_->clear(); | |
672 | |
673 SendKeyEvent(ui::VKEY_DOWN); | |
674 EXPECT_TRUE(textfield_->key_received()); | |
675 EXPECT_FALSE(textfield_->key_handled()); | |
676 textfield_->clear(); | |
677 | |
678 // Empty Textfield does not handle left/right. | |
679 textfield_->SetText(base::string16()); | |
680 SendKeyEvent(ui::VKEY_LEFT); | |
681 EXPECT_TRUE(textfield_->key_received()); | |
682 EXPECT_FALSE(textfield_->key_handled()); | |
683 textfield_->clear(); | |
684 | |
685 SendKeyEvent(ui::VKEY_RIGHT); | |
686 EXPECT_TRUE(textfield_->key_received()); | |
687 EXPECT_FALSE(textfield_->key_handled()); | |
688 textfield_->clear(); | |
689 | |
690 // Add a char. Right key should not be handled when cursor is at the end. | |
691 SendKeyEvent(ui::VKEY_B); | |
692 SendKeyEvent(ui::VKEY_RIGHT); | |
693 EXPECT_TRUE(textfield_->key_received()); | |
694 EXPECT_FALSE(textfield_->key_handled()); | |
695 textfield_->clear(); | |
696 | |
697 // First left key is handled to move cursor left to the beginning. | |
698 SendKeyEvent(ui::VKEY_LEFT); | |
699 EXPECT_TRUE(textfield_->key_received()); | |
700 EXPECT_TRUE(textfield_->key_handled()); | |
701 textfield_->clear(); | |
702 | |
703 // Now left key should not be handled. | |
704 SendKeyEvent(ui::VKEY_LEFT); | |
705 EXPECT_TRUE(textfield_->key_received()); | |
706 EXPECT_FALSE(textfield_->key_handled()); | |
707 textfield_->clear(); | |
708 } | |
709 | |
710 TEST_F(NativeTextfieldViewsTest, CursorMovement) { | |
711 InitTextfield(Textfield::STYLE_DEFAULT); | |
712 | |
713 // Test with trailing whitespace. | |
714 textfield_->SetText(ASCIIToUTF16("one two hre ")); | |
715 | |
716 // Send the cursor at the end. | |
717 SendKeyEvent(ui::VKEY_END); | |
718 | |
719 // Ctrl+Left should move the cursor just before the last word. | |
720 SendKeyEvent(ui::VKEY_LEFT, false, true); | |
721 SendKeyEvent(ui::VKEY_T); | |
722 EXPECT_STR_EQ("one two thre ", textfield_->text()); | |
723 EXPECT_STR_EQ("one two thre ", last_contents_); | |
724 | |
725 // Ctrl+Right should move the cursor to the end of the last word. | |
726 SendKeyEvent(ui::VKEY_RIGHT, false, true); | |
727 SendKeyEvent(ui::VKEY_E); | |
728 EXPECT_STR_EQ("one two three ", textfield_->text()); | |
729 EXPECT_STR_EQ("one two three ", last_contents_); | |
730 | |
731 // Ctrl+Right again should move the cursor to the end. | |
732 SendKeyEvent(ui::VKEY_RIGHT, false, true); | |
733 SendKeyEvent(ui::VKEY_BACK); | |
734 EXPECT_STR_EQ("one two three", textfield_->text()); | |
735 EXPECT_STR_EQ("one two three", last_contents_); | |
736 | |
737 // Test with leading whitespace. | |
738 textfield_->SetText(ASCIIToUTF16(" ne two")); | |
739 | |
740 // Send the cursor at the beginning. | |
741 SendKeyEvent(ui::VKEY_HOME); | |
742 | |
743 // Ctrl+Right, then Ctrl+Left should move the cursor to the beginning of the | |
744 // first word. | |
745 SendKeyEvent(ui::VKEY_RIGHT, false, true); | |
746 SendKeyEvent(ui::VKEY_LEFT, false, true); | |
747 SendKeyEvent(ui::VKEY_O); | |
748 EXPECT_STR_EQ(" one two", textfield_->text()); | |
749 EXPECT_STR_EQ(" one two", last_contents_); | |
750 | |
751 // Ctrl+Left to move the cursor to the beginning of the first word. | |
752 SendKeyEvent(ui::VKEY_LEFT, false, true); | |
753 // Ctrl+Left again should move the cursor back to the very beginning. | |
754 SendKeyEvent(ui::VKEY_LEFT, false, true); | |
755 SendKeyEvent(ui::VKEY_DELETE); | |
756 EXPECT_STR_EQ("one two", textfield_->text()); | |
757 EXPECT_STR_EQ("one two", last_contents_); | |
758 } | |
759 | |
760 TEST_F(NativeTextfieldViewsTest, FocusTraversalTest) { | |
761 InitTextfields(Textfield::STYLE_DEFAULT, 3); | |
762 textfield_->RequestFocus(); | |
763 | |
764 EXPECT_EQ(1, GetFocusedView()->id()); | |
765 widget_->GetFocusManager()->AdvanceFocus(false); | |
766 EXPECT_EQ(2, GetFocusedView()->id()); | |
767 widget_->GetFocusManager()->AdvanceFocus(false); | |
768 EXPECT_EQ(3, GetFocusedView()->id()); | |
769 // Cycle back to the first textfield. | |
770 widget_->GetFocusManager()->AdvanceFocus(false); | |
771 EXPECT_EQ(1, GetFocusedView()->id()); | |
772 | |
773 widget_->GetFocusManager()->AdvanceFocus(true); | |
774 EXPECT_EQ(3, GetFocusedView()->id()); | |
775 widget_->GetFocusManager()->AdvanceFocus(true); | |
776 EXPECT_EQ(2, GetFocusedView()->id()); | |
777 widget_->GetFocusManager()->AdvanceFocus(true); | |
778 EXPECT_EQ(1, GetFocusedView()->id()); | |
779 // Cycle back to the last textfield. | |
780 widget_->GetFocusManager()->AdvanceFocus(true); | |
781 EXPECT_EQ(3, GetFocusedView()->id()); | |
782 | |
783 // Request focus should still work. | |
784 textfield_->RequestFocus(); | |
785 EXPECT_EQ(1, GetFocusedView()->id()); | |
786 | |
787 // Test if clicking on textfield view sets the focus to textfield_. | |
788 widget_->GetFocusManager()->AdvanceFocus(true); | |
789 EXPECT_EQ(3, GetFocusedView()->id()); | |
790 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), | |
791 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
792 textfield_view_->OnMousePressed(click); | |
793 EXPECT_EQ(1, GetFocusedView()->id()); | |
794 } | |
795 | |
796 TEST_F(NativeTextfieldViewsTest, ContextMenuDisplayTest) { | |
797 InitTextfield(Textfield::STYLE_DEFAULT); | |
798 EXPECT_TRUE(textfield_->context_menu_controller()); | |
799 textfield_->SetText(ASCIIToUTF16("hello world")); | |
800 ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE); | |
801 textfield_view_->ClearEditHistory(); | |
802 EXPECT_TRUE(GetContextMenuModel()); | |
803 VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel()); | |
804 | |
805 textfield_->SelectAll(false); | |
806 VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel()); | |
807 | |
808 SendKeyEvent(ui::VKEY_T); | |
809 VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel()); | |
810 | |
811 textfield_->SelectAll(false); | |
812 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel()); | |
813 | |
814 // Exercise the "paste enabled?" check in the verifier. | |
815 SetClipboardText("Test"); | |
816 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel()); | |
817 } | |
818 | |
819 TEST_F(NativeTextfieldViewsTest, DoubleAndTripleClickTest) { | |
820 InitTextfield(Textfield::STYLE_DEFAULT); | |
821 textfield_->SetText(ASCIIToUTF16("hello world")); | |
822 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), | |
823 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
824 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), | |
825 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
826 ui::MouseEvent double_click( | |
827 ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), | |
828 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK, | |
829 ui::EF_LEFT_MOUSE_BUTTON); | |
830 | |
831 // Test for double click. | |
832 textfield_view_->OnMousePressed(click); | |
833 textfield_view_->OnMouseReleased(release); | |
834 EXPECT_TRUE(textfield_->GetSelectedText().empty()); | |
835 textfield_view_->OnMousePressed(double_click); | |
836 textfield_view_->OnMouseReleased(release); | |
837 EXPECT_STR_EQ("hello", textfield_->GetSelectedText()); | |
838 | |
839 // Test for triple click. | |
840 textfield_view_->OnMousePressed(click); | |
841 textfield_view_->OnMouseReleased(release); | |
842 EXPECT_STR_EQ("hello world", textfield_->GetSelectedText()); | |
843 | |
844 // Another click should reset back to double click. | |
845 textfield_view_->OnMousePressed(click); | |
846 textfield_view_->OnMouseReleased(release); | |
847 EXPECT_STR_EQ("hello", textfield_->GetSelectedText()); | |
848 } | |
849 | |
850 TEST_F(NativeTextfieldViewsTest, DragToSelect) { | |
851 InitTextfield(Textfield::STYLE_DEFAULT); | |
852 textfield_->SetText(ASCIIToUTF16("hello world")); | |
853 const int kStart = GetCursorPositionX(5); | |
854 const int kEnd = 500; | |
855 gfx::Point start_point(kStart, 0); | |
856 gfx::Point end_point(kEnd, 0); | |
857 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, start_point, start_point, | |
858 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
859 ui::MouseEvent click_b(ui::ET_MOUSE_PRESSED, end_point, end_point, | |
860 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
861 ui::MouseEvent drag_left(ui::ET_MOUSE_DRAGGED, gfx::Point(), gfx::Point(), | |
862 ui::EF_LEFT_MOUSE_BUTTON, 0); | |
863 ui::MouseEvent drag_right(ui::ET_MOUSE_DRAGGED, end_point, end_point, | |
864 ui::EF_LEFT_MOUSE_BUTTON, 0); | |
865 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, end_point, end_point, | |
866 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
867 textfield_view_->OnMousePressed(click_a); | |
868 EXPECT_TRUE(textfield_->GetSelectedText().empty()); | |
869 // Check that dragging left selects the beginning of the string. | |
870 textfield_view_->OnMouseDragged(drag_left); | |
871 base::string16 text_left = textfield_->GetSelectedText(); | |
872 EXPECT_STR_EQ("hello", text_left); | |
873 // Check that dragging right selects the rest of the string. | |
874 textfield_view_->OnMouseDragged(drag_right); | |
875 base::string16 text_right = textfield_->GetSelectedText(); | |
876 EXPECT_STR_EQ(" world", text_right); | |
877 // Check that releasing in the same location does not alter the selection. | |
878 textfield_view_->OnMouseReleased(release); | |
879 EXPECT_EQ(text_right, textfield_->GetSelectedText()); | |
880 // Check that dragging from beyond the text length works too. | |
881 textfield_view_->OnMousePressed(click_b); | |
882 textfield_view_->OnMouseDragged(drag_left); | |
883 textfield_view_->OnMouseReleased(release); | |
884 EXPECT_EQ(textfield_->text(), textfield_->GetSelectedText()); | |
885 } | |
886 | |
887 #if defined(OS_WIN) | |
888 TEST_F(NativeTextfieldViewsTest, DragAndDrop_AcceptDrop) { | |
889 InitTextfield(Textfield::STYLE_DEFAULT); | |
890 textfield_->SetText(ASCIIToUTF16("hello world")); | |
891 | |
892 ui::OSExchangeData data; | |
893 base::string16 string(ASCIIToUTF16("string ")); | |
894 data.SetString(string); | |
895 int formats = 0; | |
896 std::set<OSExchangeData::CustomFormat> custom_formats; | |
897 | |
898 // Ensure that disabled textfields do not accept drops. | |
899 textfield_->SetEnabled(false); | |
900 EXPECT_FALSE(textfield_view_->GetDropFormats(&formats, &custom_formats)); | |
901 EXPECT_EQ(0, formats); | |
902 EXPECT_TRUE(custom_formats.empty()); | |
903 EXPECT_FALSE(textfield_view_->CanDrop(data)); | |
904 textfield_->SetEnabled(true); | |
905 | |
906 // Ensure that read-only textfields do not accept drops. | |
907 textfield_->SetReadOnly(true); | |
908 EXPECT_FALSE(textfield_view_->GetDropFormats(&formats, &custom_formats)); | |
909 EXPECT_EQ(0, formats); | |
910 EXPECT_TRUE(custom_formats.empty()); | |
911 EXPECT_FALSE(textfield_view_->CanDrop(data)); | |
912 textfield_->SetReadOnly(false); | |
913 | |
914 // Ensure that enabled and editable textfields do accept drops. | |
915 EXPECT_TRUE(textfield_view_->GetDropFormats(&formats, &custom_formats)); | |
916 EXPECT_EQ(ui::OSExchangeData::STRING, formats); | |
917 EXPECT_TRUE(custom_formats.empty()); | |
918 EXPECT_TRUE(textfield_view_->CanDrop(data)); | |
919 gfx::Point drop_point(GetCursorPositionX(6), 0); | |
920 ui::DropTargetEvent drop(data, drop_point, drop_point, | |
921 ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE); | |
922 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE, | |
923 textfield_view_->OnDragUpdated(drop)); | |
924 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, textfield_view_->OnPerformDrop(drop)); | |
925 EXPECT_STR_EQ("hello string world", textfield_->text()); | |
926 | |
927 // Ensure that textfields do not accept non-OSExchangeData::STRING types. | |
928 ui::OSExchangeData bad_data; | |
929 bad_data.SetFilename(base::FilePath(FILE_PATH_LITERAL("x"))); | |
930 #if defined(OS_WIN) | |
931 ui::OSExchangeData::CustomFormat fmt = ui::Clipboard::GetBitmapFormatType(); | |
932 bad_data.SetPickledData(fmt, Pickle()); | |
933 bad_data.SetFileContents(base::FilePath(L"x"), "x"); | |
934 bad_data.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org")); | |
935 ui::OSExchangeData::DownloadFileInfo download(base::FilePath(), NULL); | |
936 bad_data.SetDownloadFileInfo(download); | |
937 #endif | |
938 EXPECT_FALSE(textfield_view_->CanDrop(bad_data)); | |
939 } | |
940 #endif | |
941 | |
942 TEST_F(NativeTextfieldViewsTest, DragAndDrop_InitiateDrag) { | |
943 InitTextfield(Textfield::STYLE_DEFAULT); | |
944 textfield_->SetText(ASCIIToUTF16("hello string world")); | |
945 | |
946 // Ensure the textfield will provide selected text for drag data. | |
947 base::string16 string; | |
948 ui::OSExchangeData data; | |
949 const gfx::Range kStringRange(6, 12); | |
950 textfield_->SelectRange(kStringRange); | |
951 const gfx::Point kStringPoint(GetCursorPositionX(9), 0); | |
952 textfield_view_->WriteDragDataForView(NULL, kStringPoint, &data); | |
953 EXPECT_TRUE(data.GetString(&string)); | |
954 EXPECT_EQ(textfield_->GetSelectedText(), string); | |
955 | |
956 // Ensure that disabled textfields do not support drag operations. | |
957 textfield_->SetEnabled(false); | |
958 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, | |
959 textfield_view_->GetDragOperationsForView(NULL, kStringPoint)); | |
960 textfield_->SetEnabled(true); | |
961 // Ensure that textfields without selections do not support drag operations. | |
962 textfield_->ClearSelection(); | |
963 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, | |
964 textfield_view_->GetDragOperationsForView(NULL, kStringPoint)); | |
965 textfield_->SelectRange(kStringRange); | |
966 // Ensure that password textfields do not support drag operations. | |
967 textfield_->SetObscured(true); | |
968 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, | |
969 textfield_view_->GetDragOperationsForView(NULL, kStringPoint)); | |
970 textfield_->SetObscured(false); | |
971 // Ensure that textfields only initiate drag operations inside the selection. | |
972 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, kStringPoint, kStringPoint, | |
973 ui::EF_LEFT_MOUSE_BUTTON, | |
974 ui::EF_LEFT_MOUSE_BUTTON); | |
975 textfield_view_->OnMousePressed(press_event); | |
976 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, | |
977 textfield_view_->GetDragOperationsForView(NULL, gfx::Point())); | |
978 EXPECT_FALSE(textfield_view_->CanStartDragForView(NULL, gfx::Point(), | |
979 gfx::Point())); | |
980 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, | |
981 textfield_view_->GetDragOperationsForView(NULL, kStringPoint)); | |
982 EXPECT_TRUE(textfield_view_->CanStartDragForView(NULL, kStringPoint, | |
983 gfx::Point())); | |
984 // Ensure that textfields support local moves. | |
985 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY, | |
986 textfield_view_->GetDragOperationsForView(textfield_view_, kStringPoint)); | |
987 } | |
988 | |
989 TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheRight) { | |
990 InitTextfield(Textfield::STYLE_DEFAULT); | |
991 textfield_->SetText(ASCIIToUTF16("hello world")); | |
992 | |
993 base::string16 string; | |
994 ui::OSExchangeData data; | |
995 int formats = 0; | |
996 int operations = 0; | |
997 std::set<OSExchangeData::CustomFormat> custom_formats; | |
998 | |
999 // Start dragging "ello". | |
1000 textfield_->SelectRange(gfx::Range(1, 5)); | |
1001 gfx::Point point(GetCursorPositionX(3), 0); | |
1002 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point, | |
1003 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
1004 textfield_view_->OnMousePressed(click_a); | |
1005 EXPECT_TRUE(textfield_view_->CanStartDragForView(textfield_view_, | |
1006 click_a.location(), gfx::Point())); | |
1007 operations = textfield_view_->GetDragOperationsForView(textfield_view_, | |
1008 click_a.location()); | |
1009 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY, | |
1010 operations); | |
1011 textfield_view_->WriteDragDataForView(NULL, click_a.location(), &data); | |
1012 EXPECT_TRUE(data.GetString(&string)); | |
1013 EXPECT_EQ(textfield_->GetSelectedText(), string); | |
1014 EXPECT_TRUE(textfield_view_->GetDropFormats(&formats, &custom_formats)); | |
1015 EXPECT_EQ(ui::OSExchangeData::STRING, formats); | |
1016 EXPECT_TRUE(custom_formats.empty()); | |
1017 | |
1018 // Drop "ello" after "w". | |
1019 const gfx::Point kDropPoint(GetCursorPositionX(7), 0); | |
1020 EXPECT_TRUE(textfield_view_->CanDrop(data)); | |
1021 ui::DropTargetEvent drop_a(data, kDropPoint, kDropPoint, operations); | |
1022 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, | |
1023 textfield_view_->OnDragUpdated(drop_a)); | |
1024 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, | |
1025 textfield_view_->OnPerformDrop(drop_a)); | |
1026 EXPECT_STR_EQ("h welloorld", textfield_->text()); | |
1027 textfield_view_->OnDragDone(); | |
1028 | |
1029 // Undo/Redo the drag&drop change. | |
1030 SendKeyEvent(ui::VKEY_Z, false, true); | |
1031 EXPECT_STR_EQ("hello world", textfield_->text()); | |
1032 SendKeyEvent(ui::VKEY_Z, false, true); | |
1033 EXPECT_STR_EQ("", textfield_->text()); | |
1034 SendKeyEvent(ui::VKEY_Z, false, true); | |
1035 EXPECT_STR_EQ("", textfield_->text()); | |
1036 SendKeyEvent(ui::VKEY_Y, false, true); | |
1037 EXPECT_STR_EQ("hello world", textfield_->text()); | |
1038 SendKeyEvent(ui::VKEY_Y, false, true); | |
1039 EXPECT_STR_EQ("h welloorld", textfield_->text()); | |
1040 SendKeyEvent(ui::VKEY_Y, false, true); | |
1041 EXPECT_STR_EQ("h welloorld", textfield_->text()); | |
1042 } | |
1043 | |
1044 TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheLeft) { | |
1045 InitTextfield(Textfield::STYLE_DEFAULT); | |
1046 textfield_->SetText(ASCIIToUTF16("hello world")); | |
1047 | |
1048 base::string16 string; | |
1049 ui::OSExchangeData data; | |
1050 int formats = 0; | |
1051 int operations = 0; | |
1052 std::set<OSExchangeData::CustomFormat> custom_formats; | |
1053 | |
1054 // Start dragging " worl". | |
1055 textfield_->SelectRange(gfx::Range(5, 10)); | |
1056 gfx::Point point(GetCursorPositionX(7), 0); | |
1057 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point, | |
1058 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
1059 textfield_view_->OnMousePressed(click_a); | |
1060 EXPECT_TRUE(textfield_view_->CanStartDragForView(textfield_view_, | |
1061 click_a.location(), gfx::Point())); | |
1062 operations = textfield_view_->GetDragOperationsForView(textfield_view_, | |
1063 click_a.location()); | |
1064 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY, | |
1065 operations); | |
1066 textfield_view_->WriteDragDataForView(NULL, click_a.location(), &data); | |
1067 EXPECT_TRUE(data.GetString(&string)); | |
1068 EXPECT_EQ(textfield_->GetSelectedText(), string); | |
1069 EXPECT_TRUE(textfield_view_->GetDropFormats(&formats, &custom_formats)); | |
1070 EXPECT_EQ(ui::OSExchangeData::STRING, formats); | |
1071 EXPECT_TRUE(custom_formats.empty()); | |
1072 | |
1073 // Drop " worl" after "h". | |
1074 EXPECT_TRUE(textfield_view_->CanDrop(data)); | |
1075 gfx::Point drop_point(GetCursorPositionX(1), 0); | |
1076 ui::DropTargetEvent drop_a(data, drop_point, drop_point, operations); | |
1077 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, | |
1078 textfield_view_->OnDragUpdated(drop_a)); | |
1079 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, | |
1080 textfield_view_->OnPerformDrop(drop_a)); | |
1081 EXPECT_STR_EQ("h worlellod", textfield_->text()); | |
1082 textfield_view_->OnDragDone(); | |
1083 | |
1084 // Undo/Redo the drag&drop change. | |
1085 SendKeyEvent(ui::VKEY_Z, false, true); | |
1086 EXPECT_STR_EQ("hello world", textfield_->text()); | |
1087 SendKeyEvent(ui::VKEY_Z, false, true); | |
1088 EXPECT_STR_EQ("", textfield_->text()); | |
1089 SendKeyEvent(ui::VKEY_Z, false, true); | |
1090 EXPECT_STR_EQ("", textfield_->text()); | |
1091 SendKeyEvent(ui::VKEY_Y, false, true); | |
1092 EXPECT_STR_EQ("hello world", textfield_->text()); | |
1093 SendKeyEvent(ui::VKEY_Y, false, true); | |
1094 EXPECT_STR_EQ("h worlellod", textfield_->text()); | |
1095 SendKeyEvent(ui::VKEY_Y, false, true); | |
1096 EXPECT_STR_EQ("h worlellod", textfield_->text()); | |
1097 } | |
1098 | |
1099 TEST_F(NativeTextfieldViewsTest, DragAndDrop_Canceled) { | |
1100 InitTextfield(Textfield::STYLE_DEFAULT); | |
1101 textfield_->SetText(ASCIIToUTF16("hello world")); | |
1102 | |
1103 // Start dragging "worl". | |
1104 textfield_->SelectRange(gfx::Range(6, 10)); | |
1105 gfx::Point point(GetCursorPositionX(8), 0); | |
1106 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point, | |
1107 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
1108 textfield_view_->OnMousePressed(click); | |
1109 ui::OSExchangeData data; | |
1110 textfield_view_->WriteDragDataForView(NULL, click.location(), &data); | |
1111 EXPECT_TRUE(textfield_view_->CanDrop(data)); | |
1112 // Drag the text over somewhere valid, outside the current selection. | |
1113 gfx::Point drop_point(GetCursorPositionX(2), 0); | |
1114 ui::DropTargetEvent drop(data, drop_point, drop_point, | |
1115 ui::DragDropTypes::DRAG_MOVE); | |
1116 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_view_->OnDragUpdated(drop)); | |
1117 // "Cancel" the drag, via move and release over the selection, and OnDragDone. | |
1118 gfx::Point drag_point(GetCursorPositionX(9), 0); | |
1119 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, drag_point, drag_point, | |
1120 ui::EF_LEFT_MOUSE_BUTTON, 0); | |
1121 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, drag_point, drag_point, | |
1122 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
1123 textfield_view_->OnMouseDragged(drag); | |
1124 textfield_view_->OnMouseReleased(release); | |
1125 textfield_view_->OnDragDone(); | |
1126 EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_->text()); | |
1127 } | |
1128 | |
1129 TEST_F(NativeTextfieldViewsTest, ReadOnlyTest) { | |
1130 InitTextfield(Textfield::STYLE_DEFAULT); | |
1131 textfield_->SetText(ASCIIToUTF16("read only")); | |
1132 textfield_->SetReadOnly(true); | |
1133 EXPECT_TRUE(textfield_->enabled()); | |
1134 EXPECT_TRUE(textfield_->focusable()); | |
1135 | |
1136 SendKeyEvent(ui::VKEY_HOME); | |
1137 EXPECT_EQ(0U, textfield_->GetCursorPosition()); | |
1138 SendKeyEvent(ui::VKEY_END); | |
1139 EXPECT_EQ(9U, textfield_->GetCursorPosition()); | |
1140 | |
1141 SendKeyEvent(ui::VKEY_LEFT, false, false); | |
1142 EXPECT_EQ(8U, textfield_->GetCursorPosition()); | |
1143 SendKeyEvent(ui::VKEY_LEFT, false, true); | |
1144 EXPECT_EQ(5U, textfield_->GetCursorPosition()); | |
1145 SendKeyEvent(ui::VKEY_LEFT, true, true); | |
1146 EXPECT_EQ(0U, textfield_->GetCursorPosition()); | |
1147 EXPECT_STR_EQ("read ", textfield_->GetSelectedText()); | |
1148 textfield_->SelectAll(false); | |
1149 EXPECT_STR_EQ("read only", textfield_->GetSelectedText()); | |
1150 | |
1151 // Cut should be disabled. | |
1152 SetClipboardText("Test"); | |
1153 EXPECT_FALSE(textfield_view_->IsCommandIdEnabled(IDS_APP_CUT)); | |
1154 textfield_view_->ExecuteCommand(IDS_APP_CUT, 0); | |
1155 SendKeyEvent(ui::VKEY_X, false, true); | |
1156 SendKeyEvent(ui::VKEY_DELETE, true, false); | |
1157 EXPECT_STR_EQ("Test", base::string16(GetClipboardText())); | |
1158 EXPECT_STR_EQ("read only", textfield_->text()); | |
1159 | |
1160 // Paste should be disabled. | |
1161 EXPECT_FALSE(textfield_view_->IsCommandIdEnabled(IDS_APP_PASTE)); | |
1162 textfield_view_->ExecuteCommand(IDS_APP_PASTE, 0); | |
1163 SendKeyEvent(ui::VKEY_V, false, true); | |
1164 SendKeyEvent(ui::VKEY_INSERT, true, false); | |
1165 EXPECT_STR_EQ("read only", textfield_->text()); | |
1166 | |
1167 // Copy should work normally. | |
1168 SetClipboardText("Test"); | |
1169 EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_COPY)); | |
1170 textfield_view_->ExecuteCommand(IDS_APP_COPY, 0); | |
1171 EXPECT_STR_EQ("read only", base::string16(GetClipboardText())); | |
1172 SetClipboardText("Test"); | |
1173 SendKeyEvent(ui::VKEY_C, false, true); | |
1174 EXPECT_STR_EQ("read only", base::string16(GetClipboardText())); | |
1175 SetClipboardText("Test"); | |
1176 SendKeyEvent(ui::VKEY_INSERT, false, true); | |
1177 EXPECT_STR_EQ("read only", base::string16(GetClipboardText())); | |
1178 | |
1179 // SetText should work even in read only mode. | |
1180 textfield_->SetText(ASCIIToUTF16(" four five six ")); | |
1181 EXPECT_STR_EQ(" four five six ", textfield_->text()); | |
1182 | |
1183 textfield_->SelectAll(false); | |
1184 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); | |
1185 | |
1186 // Text field is unmodifiable and selection shouldn't change. | |
1187 SendKeyEvent(ui::VKEY_DELETE); | |
1188 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); | |
1189 SendKeyEvent(ui::VKEY_BACK); | |
1190 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); | |
1191 SendKeyEvent(ui::VKEY_T); | |
1192 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText()); | |
1193 } | |
1194 | |
1195 TEST_F(NativeTextfieldViewsTest, TextInputClientTest) { | |
1196 InitTextfield(Textfield::STYLE_DEFAULT); | |
1197 ui::TextInputClient* client = textfield_->GetTextInputClient(); | |
1198 EXPECT_TRUE(client); | |
1199 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, client->GetTextInputType()); | |
1200 | |
1201 textfield_->SetText(ASCIIToUTF16("0123456789")); | |
1202 gfx::Range range; | |
1203 EXPECT_TRUE(client->GetTextRange(&range)); | |
1204 EXPECT_EQ(0U, range.start()); | |
1205 EXPECT_EQ(10U, range.end()); | |
1206 | |
1207 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(1, 4))); | |
1208 EXPECT_TRUE(client->GetSelectionRange(&range)); | |
1209 EXPECT_EQ(gfx::Range(1, 4), range); | |
1210 | |
1211 // This code can't be compiled because of a bug in base::Callback. | |
1212 #if 0 | |
1213 GetTextHelper helper; | |
1214 base::Callback<void(base::string16)> callback = | |
1215 base::Bind(&GetTextHelper::set_text, base::Unretained(&helper)); | |
1216 | |
1217 EXPECT_TRUE(client->GetTextFromRange(range, callback)); | |
1218 EXPECT_STR_EQ("123", helper.text()); | |
1219 #endif | |
1220 | |
1221 EXPECT_TRUE(client->DeleteRange(range)); | |
1222 EXPECT_STR_EQ("0456789", textfield_->text()); | |
1223 | |
1224 ui::CompositionText composition; | |
1225 composition.text = UTF8ToUTF16("321"); | |
1226 // Set composition through input method. | |
1227 input_method_->Clear(); | |
1228 input_method_->SetCompositionTextForNextKey(composition); | |
1229 textfield_->clear(); | |
1230 | |
1231 on_before_user_action_ = on_after_user_action_ = 0; | |
1232 SendKeyEvent(ui::VKEY_A); | |
1233 EXPECT_TRUE(textfield_->key_received()); | |
1234 EXPECT_FALSE(textfield_->key_handled()); | |
1235 EXPECT_TRUE(client->HasCompositionText()); | |
1236 EXPECT_TRUE(client->GetCompositionTextRange(&range)); | |
1237 EXPECT_STR_EQ("0321456789", textfield_->text()); | |
1238 EXPECT_EQ(gfx::Range(1, 4), range); | |
1239 EXPECT_EQ(2, on_before_user_action_); | |
1240 EXPECT_EQ(2, on_after_user_action_); | |
1241 | |
1242 input_method_->SetResultTextForNextKey(UTF8ToUTF16("123")); | |
1243 on_before_user_action_ = on_after_user_action_ = 0; | |
1244 textfield_->clear(); | |
1245 SendKeyEvent(ui::VKEY_A); | |
1246 EXPECT_TRUE(textfield_->key_received()); | |
1247 EXPECT_FALSE(textfield_->key_handled()); | |
1248 EXPECT_FALSE(client->HasCompositionText()); | |
1249 EXPECT_FALSE(input_method_->cancel_composition_called()); | |
1250 EXPECT_STR_EQ("0123456789", textfield_->text()); | |
1251 EXPECT_EQ(2, on_before_user_action_); | |
1252 EXPECT_EQ(2, on_after_user_action_); | |
1253 | |
1254 input_method_->Clear(); | |
1255 input_method_->SetCompositionTextForNextKey(composition); | |
1256 textfield_->clear(); | |
1257 SendKeyEvent(ui::VKEY_A); | |
1258 EXPECT_TRUE(client->HasCompositionText()); | |
1259 EXPECT_STR_EQ("0123321456789", textfield_->text()); | |
1260 | |
1261 on_before_user_action_ = on_after_user_action_ = 0; | |
1262 textfield_->clear(); | |
1263 SendKeyEvent(ui::VKEY_RIGHT); | |
1264 EXPECT_FALSE(client->HasCompositionText()); | |
1265 EXPECT_TRUE(input_method_->cancel_composition_called()); | |
1266 EXPECT_TRUE(textfield_->key_received()); | |
1267 EXPECT_TRUE(textfield_->key_handled()); | |
1268 EXPECT_STR_EQ("0123321456789", textfield_->text()); | |
1269 EXPECT_EQ(8U, textfield_->GetCursorPosition()); | |
1270 EXPECT_EQ(1, on_before_user_action_); | |
1271 EXPECT_EQ(1, on_after_user_action_); | |
1272 | |
1273 textfield_->clear(); | |
1274 textfield_->SetText(ASCIIToUTF16("0123456789")); | |
1275 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(5, 5))); | |
1276 client->ExtendSelectionAndDelete(4, 2); | |
1277 EXPECT_STR_EQ("0789", textfield_->text()); | |
1278 | |
1279 // On{Before,After}UserAction should be called by whatever user action | |
1280 // triggers clearing or setting a selection if appropriate. | |
1281 on_before_user_action_ = on_after_user_action_ = 0; | |
1282 textfield_->clear(); | |
1283 textfield_->ClearSelection(); | |
1284 textfield_->SelectAll(false); | |
1285 EXPECT_EQ(0, on_before_user_action_); | |
1286 EXPECT_EQ(0, on_after_user_action_); | |
1287 | |
1288 input_method_->Clear(); | |
1289 textfield_->SetReadOnly(true); | |
1290 EXPECT_TRUE(input_method_->text_input_type_changed()); | |
1291 EXPECT_FALSE(textfield_->GetTextInputClient()); | |
1292 | |
1293 textfield_->SetReadOnly(false); | |
1294 input_method_->Clear(); | |
1295 textfield_->SetObscured(true); | |
1296 EXPECT_TRUE(input_method_->text_input_type_changed()); | |
1297 EXPECT_TRUE(textfield_->GetTextInputClient()); | |
1298 } | |
1299 | |
1300 TEST_F(NativeTextfieldViewsTest, UndoRedoTest) { | |
1301 InitTextfield(Textfield::STYLE_DEFAULT); | |
1302 SendKeyEvent(ui::VKEY_A); | |
1303 EXPECT_STR_EQ("a", textfield_->text()); | |
1304 SendKeyEvent(ui::VKEY_Z, false, true); | |
1305 EXPECT_STR_EQ("", textfield_->text()); | |
1306 SendKeyEvent(ui::VKEY_Z, false, true); | |
1307 EXPECT_STR_EQ("", textfield_->text()); | |
1308 SendKeyEvent(ui::VKEY_Y, false, true); | |
1309 EXPECT_STR_EQ("a", textfield_->text()); | |
1310 SendKeyEvent(ui::VKEY_Y, false, true); | |
1311 EXPECT_STR_EQ("a", textfield_->text()); | |
1312 | |
1313 // AppendText | |
1314 textfield_->AppendText(ASCIIToUTF16("b")); | |
1315 last_contents_.clear(); // AppendText doesn't call ContentsChanged. | |
1316 EXPECT_STR_EQ("ab", textfield_->text()); | |
1317 SendKeyEvent(ui::VKEY_Z, false, true); | |
1318 EXPECT_STR_EQ("a", textfield_->text()); | |
1319 SendKeyEvent(ui::VKEY_Y, false, true); | |
1320 EXPECT_STR_EQ("ab", textfield_->text()); | |
1321 | |
1322 // SetText | |
1323 SendKeyEvent(ui::VKEY_C); | |
1324 // Undo'ing append moves the cursor to the end for now. | |
1325 // no-op SetText won't add new edit. See TextfieldViewsModel::SetText | |
1326 // description. | |
1327 EXPECT_STR_EQ("abc", textfield_->text()); | |
1328 textfield_->SetText(ASCIIToUTF16("abc")); | |
1329 EXPECT_STR_EQ("abc", textfield_->text()); | |
1330 SendKeyEvent(ui::VKEY_Z, false, true); | |
1331 EXPECT_STR_EQ("ab", textfield_->text()); | |
1332 SendKeyEvent(ui::VKEY_Y, false, true); | |
1333 EXPECT_STR_EQ("abc", textfield_->text()); | |
1334 SendKeyEvent(ui::VKEY_Y, false, true); | |
1335 EXPECT_STR_EQ("abc", textfield_->text()); | |
1336 textfield_->SetText(ASCIIToUTF16("123")); | |
1337 textfield_->SetText(ASCIIToUTF16("123")); | |
1338 EXPECT_STR_EQ("123", textfield_->text()); | |
1339 SendKeyEvent(ui::VKEY_END, false, false); | |
1340 SendKeyEvent(ui::VKEY_4, false, false); | |
1341 EXPECT_STR_EQ("1234", textfield_->text()); | |
1342 last_contents_.clear(); | |
1343 SendKeyEvent(ui::VKEY_Z, false, true); | |
1344 EXPECT_STR_EQ("123", textfield_->text()); | |
1345 SendKeyEvent(ui::VKEY_Z, false, true); | |
1346 // the insert edit "c" and set edit "123" are merged to single edit, | |
1347 // so text becomes "ab" after undo. | |
1348 EXPECT_STR_EQ("ab", textfield_->text()); | |
1349 SendKeyEvent(ui::VKEY_Z, false, true); | |
1350 EXPECT_STR_EQ("a", textfield_->text()); | |
1351 SendKeyEvent(ui::VKEY_Y, false, true); | |
1352 EXPECT_STR_EQ("ab", textfield_->text()); | |
1353 SendKeyEvent(ui::VKEY_Y, false, true); | |
1354 EXPECT_STR_EQ("123", textfield_->text()); | |
1355 SendKeyEvent(ui::VKEY_Y, false, true); | |
1356 EXPECT_STR_EQ("1234", textfield_->text()); | |
1357 | |
1358 // Undoing to the same text shouldn't call ContentsChanged. | |
1359 SendKeyEvent(ui::VKEY_A, false, true); // select all | |
1360 SendKeyEvent(ui::VKEY_A); | |
1361 EXPECT_STR_EQ("a", textfield_->text()); | |
1362 SendKeyEvent(ui::VKEY_B); | |
1363 SendKeyEvent(ui::VKEY_C); | |
1364 EXPECT_STR_EQ("abc", textfield_->text()); | |
1365 SendKeyEvent(ui::VKEY_Z, false, true); | |
1366 EXPECT_STR_EQ("1234", textfield_->text()); | |
1367 SendKeyEvent(ui::VKEY_Y, false, true); | |
1368 EXPECT_STR_EQ("abc", textfield_->text()); | |
1369 | |
1370 // Delete/Backspace | |
1371 SendKeyEvent(ui::VKEY_BACK); | |
1372 EXPECT_STR_EQ("ab", textfield_->text()); | |
1373 SendKeyEvent(ui::VKEY_HOME); | |
1374 SendKeyEvent(ui::VKEY_DELETE); | |
1375 EXPECT_STR_EQ("b", textfield_->text()); | |
1376 SendKeyEvent(ui::VKEY_A, false, true); | |
1377 SendKeyEvent(ui::VKEY_DELETE); | |
1378 EXPECT_STR_EQ("", textfield_->text()); | |
1379 SendKeyEvent(ui::VKEY_Z, false, true); | |
1380 EXPECT_STR_EQ("b", textfield_->text()); | |
1381 SendKeyEvent(ui::VKEY_Z, false, true); | |
1382 EXPECT_STR_EQ("ab", textfield_->text()); | |
1383 SendKeyEvent(ui::VKEY_Z, false, true); | |
1384 EXPECT_STR_EQ("abc", textfield_->text()); | |
1385 SendKeyEvent(ui::VKEY_Y, false, true); | |
1386 EXPECT_STR_EQ("ab", textfield_->text()); | |
1387 SendKeyEvent(ui::VKEY_Y, false, true); | |
1388 EXPECT_STR_EQ("b", textfield_->text()); | |
1389 SendKeyEvent(ui::VKEY_Y, false, true); | |
1390 EXPECT_STR_EQ("", textfield_->text()); | |
1391 SendKeyEvent(ui::VKEY_Y, false, true); | |
1392 EXPECT_STR_EQ("", textfield_->text()); | |
1393 } | |
1394 | |
1395 TEST_F(NativeTextfieldViewsTest, CutCopyPaste) { | |
1396 InitTextfield(Textfield::STYLE_DEFAULT); | |
1397 | |
1398 // Ensure IDS_APP_CUT cuts. | |
1399 textfield_->SetText(ASCIIToUTF16("123")); | |
1400 textfield_->SelectAll(false); | |
1401 EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_CUT)); | |
1402 textfield_view_->ExecuteCommand(IDS_APP_CUT, 0); | |
1403 EXPECT_STR_EQ("123", base::string16(GetClipboardText())); | |
1404 EXPECT_STR_EQ("", textfield_->text()); | |
1405 | |
1406 // Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing. | |
1407 textfield_->SetText(ASCIIToUTF16("456")); | |
1408 textfield_->SelectAll(false); | |
1409 SendKeyEvent(ui::VKEY_X, true, false, true, false); | |
1410 EXPECT_STR_EQ("123", base::string16(GetClipboardText())); | |
1411 EXPECT_STR_EQ("456", textfield_->text()); | |
1412 SendKeyEvent(ui::VKEY_X, false, true); | |
1413 EXPECT_STR_EQ("456", base::string16(GetClipboardText())); | |
1414 EXPECT_STR_EQ("", textfield_->text()); | |
1415 | |
1416 // Ensure [Shift]+[Delete] cuts. | |
1417 textfield_->SetText(ASCIIToUTF16("123")); | |
1418 textfield_->SelectAll(false); | |
1419 SendKeyEvent(ui::VKEY_DELETE, true, false); | |
1420 EXPECT_STR_EQ("123", base::string16(GetClipboardText())); | |
1421 EXPECT_STR_EQ("", textfield_->text()); | |
1422 | |
1423 // Ensure IDS_APP_COPY copies. | |
1424 textfield_->SetText(ASCIIToUTF16("789")); | |
1425 textfield_->SelectAll(false); | |
1426 EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_COPY)); | |
1427 textfield_view_->ExecuteCommand(IDS_APP_COPY, 0); | |
1428 EXPECT_STR_EQ("789", base::string16(GetClipboardText())); | |
1429 | |
1430 // Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing. | |
1431 textfield_->SetText(ASCIIToUTF16("012")); | |
1432 textfield_->SelectAll(false); | |
1433 SendKeyEvent(ui::VKEY_C, true, false, true, false); | |
1434 EXPECT_STR_EQ("789", base::string16(GetClipboardText())); | |
1435 SendKeyEvent(ui::VKEY_C, false, true); | |
1436 EXPECT_STR_EQ("012", base::string16(GetClipboardText())); | |
1437 | |
1438 // Ensure [Ctrl]+[Insert] copies. | |
1439 textfield_->SetText(ASCIIToUTF16("345")); | |
1440 textfield_->SelectAll(false); | |
1441 SendKeyEvent(ui::VKEY_INSERT, false, true); | |
1442 EXPECT_STR_EQ("345", base::string16(GetClipboardText())); | |
1443 EXPECT_STR_EQ("345", textfield_->text()); | |
1444 | |
1445 // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes; | |
1446 // also ensure that [Ctrl]+[Alt]+[V] does nothing. | |
1447 SetClipboardText("abc"); | |
1448 textfield_->SetText(base::string16()); | |
1449 EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_PASTE)); | |
1450 textfield_view_->ExecuteCommand(IDS_APP_PASTE, 0); | |
1451 EXPECT_STR_EQ("abc", textfield_->text()); | |
1452 SendKeyEvent(ui::VKEY_V, false, true); | |
1453 EXPECT_STR_EQ("abcabc", textfield_->text()); | |
1454 SendKeyEvent(ui::VKEY_INSERT, true, false); | |
1455 EXPECT_STR_EQ("abcabcabc", textfield_->text()); | |
1456 SendKeyEvent(ui::VKEY_V, true, false, true, false); | |
1457 EXPECT_STR_EQ("abcabcabc", textfield_->text()); | |
1458 | |
1459 // Ensure [Ctrl]+[Shift]+[Insert] is a no-op. | |
1460 textfield_->SelectAll(false); | |
1461 SendKeyEvent(ui::VKEY_INSERT, true, true); | |
1462 EXPECT_STR_EQ("abc", base::string16(GetClipboardText())); | |
1463 EXPECT_STR_EQ("abcabcabc", textfield_->text()); | |
1464 } | |
1465 | |
1466 TEST_F(NativeTextfieldViewsTest, OvertypeMode) { | |
1467 InitTextfield(Textfield::STYLE_DEFAULT); | |
1468 // Overtype mode should be disabled (no-op [Insert]). | |
1469 textfield_->SetText(ASCIIToUTF16("2")); | |
1470 SendKeyEvent(ui::VKEY_HOME); | |
1471 SendKeyEvent(ui::VKEY_INSERT); | |
1472 SendKeyEvent(ui::VKEY_1, false, false); | |
1473 EXPECT_STR_EQ("12", textfield_->text()); | |
1474 } | |
1475 | |
1476 TEST_F(NativeTextfieldViewsTest, TextCursorDisplayTest) { | |
1477 InitTextfield(Textfield::STYLE_DEFAULT); | |
1478 // LTR-RTL string in LTR context. | |
1479 SendKeyEvent('a'); | |
1480 EXPECT_STR_EQ("a", textfield_->text()); | |
1481 int x = GetCursorBounds().x(); | |
1482 int prev_x = x; | |
1483 | |
1484 SendKeyEvent('b'); | |
1485 EXPECT_STR_EQ("ab", textfield_->text()); | |
1486 x = GetCursorBounds().x(); | |
1487 EXPECT_LT(prev_x, x); | |
1488 prev_x = x; | |
1489 | |
1490 SendKeyEvent(0x05E1); | |
1491 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text()); | |
1492 x = GetCursorBounds().x(); | |
1493 EXPECT_EQ(prev_x, x); | |
1494 | |
1495 SendKeyEvent(0x05E2); | |
1496 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text()); | |
1497 x = GetCursorBounds().x(); | |
1498 EXPECT_EQ(prev_x, x); | |
1499 | |
1500 // Clear text. | |
1501 SendKeyEvent(ui::VKEY_A, false, true); | |
1502 SendKeyEvent('\n'); | |
1503 | |
1504 // RTL-LTR string in LTR context. | |
1505 SendKeyEvent(0x05E1); | |
1506 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text()); | |
1507 x = GetCursorBounds().x(); | |
1508 EXPECT_EQ(GetDisplayRect().x(), x); | |
1509 prev_x = x; | |
1510 | |
1511 SendKeyEvent(0x05E2); | |
1512 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text()); | |
1513 x = GetCursorBounds().x(); | |
1514 EXPECT_EQ(prev_x, x); | |
1515 | |
1516 SendKeyEvent('a'); | |
1517 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text()); | |
1518 x = GetCursorBounds().x(); | |
1519 EXPECT_LT(prev_x, x); | |
1520 prev_x = x; | |
1521 | |
1522 SendKeyEvent('b'); | |
1523 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text()); | |
1524 x = GetCursorBounds().x(); | |
1525 EXPECT_LT(prev_x, x); | |
1526 } | |
1527 | |
1528 TEST_F(NativeTextfieldViewsTest, TextCursorDisplayInRTLTest) { | |
1529 std::string locale = l10n_util::GetApplicationLocale(""); | |
1530 base::i18n::SetICUDefaultLocale("he"); | |
1531 | |
1532 InitTextfield(Textfield::STYLE_DEFAULT); | |
1533 // LTR-RTL string in RTL context. | |
1534 SendKeyEvent('a'); | |
1535 EXPECT_STR_EQ("a", textfield_->text()); | |
1536 int x = GetCursorBounds().x(); | |
1537 EXPECT_EQ(GetDisplayRect().right() - 1, x); | |
1538 int prev_x = x; | |
1539 | |
1540 SendKeyEvent('b'); | |
1541 EXPECT_STR_EQ("ab", textfield_->text()); | |
1542 x = GetCursorBounds().x(); | |
1543 EXPECT_EQ(prev_x, x); | |
1544 | |
1545 SendKeyEvent(0x05E1); | |
1546 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text()); | |
1547 x = GetCursorBounds().x(); | |
1548 EXPECT_GT(prev_x, x); | |
1549 prev_x = x; | |
1550 | |
1551 SendKeyEvent(0x05E2); | |
1552 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text()); | |
1553 x = GetCursorBounds().x(); | |
1554 EXPECT_GT(prev_x, x); | |
1555 | |
1556 SendKeyEvent(ui::VKEY_A, false, true); | |
1557 SendKeyEvent('\n'); | |
1558 | |
1559 // RTL-LTR string in RTL context. | |
1560 SendKeyEvent(0x05E1); | |
1561 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text()); | |
1562 x = GetCursorBounds().x(); | |
1563 prev_x = x; | |
1564 | |
1565 SendKeyEvent(0x05E2); | |
1566 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text()); | |
1567 x = GetCursorBounds().x(); | |
1568 EXPECT_GT(prev_x, x); | |
1569 prev_x = x; | |
1570 | |
1571 SendKeyEvent('a'); | |
1572 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text()); | |
1573 x = GetCursorBounds().x(); | |
1574 EXPECT_EQ(prev_x, x); | |
1575 prev_x = x; | |
1576 | |
1577 SendKeyEvent('b'); | |
1578 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text()); | |
1579 x = GetCursorBounds().x(); | |
1580 EXPECT_EQ(prev_x, x); | |
1581 | |
1582 // Reset locale. | |
1583 base::i18n::SetICUDefaultLocale(locale); | |
1584 } | |
1585 | |
1586 TEST_F(NativeTextfieldViewsTest, HitInsideTextAreaTest) { | |
1587 InitTextfield(Textfield::STYLE_DEFAULT); | |
1588 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2")); | |
1589 std::vector<gfx::Rect> cursor_bounds; | |
1590 | |
1591 // Save each cursor bound. | |
1592 gfx::SelectionModel sel(0, gfx::CURSOR_FORWARD); | |
1593 cursor_bounds.push_back(GetCursorBounds(sel)); | |
1594 | |
1595 sel = gfx::SelectionModel(1, gfx::CURSOR_BACKWARD); | |
1596 gfx::Rect bound = GetCursorBounds(sel); | |
1597 sel = gfx::SelectionModel(1, gfx::CURSOR_FORWARD); | |
1598 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x()); | |
1599 cursor_bounds.push_back(bound); | |
1600 | |
1601 // Check that a cursor at the end of the Latin portion of the text is at the | |
1602 // same position as a cursor placed at the end of the RTL Hebrew portion. | |
1603 sel = gfx::SelectionModel(2, gfx::CURSOR_BACKWARD); | |
1604 bound = GetCursorBounds(sel); | |
1605 sel = gfx::SelectionModel(4, gfx::CURSOR_BACKWARD); | |
1606 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x()); | |
1607 cursor_bounds.push_back(bound); | |
1608 | |
1609 sel = gfx::SelectionModel(3, gfx::CURSOR_BACKWARD); | |
1610 bound = GetCursorBounds(sel); | |
1611 sel = gfx::SelectionModel(3, gfx::CURSOR_FORWARD); | |
1612 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x()); | |
1613 cursor_bounds.push_back(bound); | |
1614 | |
1615 sel = gfx::SelectionModel(2, gfx::CURSOR_FORWARD); | |
1616 bound = GetCursorBounds(sel); | |
1617 sel = gfx::SelectionModel(4, gfx::CURSOR_FORWARD); | |
1618 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x()); | |
1619 cursor_bounds.push_back(bound); | |
1620 | |
1621 // Expected cursor position when clicking left and right of each character. | |
1622 size_t cursor_pos_expected[] = {0, 1, 1, 2, 4, 3, 3, 2}; | |
1623 | |
1624 int index = 0; | |
1625 for (int i = 0; i < static_cast<int>(cursor_bounds.size() - 1); ++i) { | |
1626 int half_width = (cursor_bounds[i + 1].x() - cursor_bounds[i].x()) / 2; | |
1627 MouseClick(cursor_bounds[i], half_width / 2); | |
1628 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition()); | |
1629 | |
1630 // To avoid trigger double click. Not using sleep() since it takes longer | |
1631 // for the test to run if using sleep(). | |
1632 NonClientMouseClick(); | |
1633 | |
1634 MouseClick(cursor_bounds[i + 1], - (half_width / 2)); | |
1635 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition()); | |
1636 | |
1637 NonClientMouseClick(); | |
1638 } | |
1639 } | |
1640 | |
1641 TEST_F(NativeTextfieldViewsTest, HitOutsideTextAreaTest) { | |
1642 InitTextfield(Textfield::STYLE_DEFAULT); | |
1643 | |
1644 // LTR-RTL string in LTR context. | |
1645 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2")); | |
1646 | |
1647 SendKeyEvent(ui::VKEY_HOME); | |
1648 gfx::Rect bound = GetCursorBounds(); | |
1649 MouseClick(bound, -10); | |
1650 EXPECT_EQ(bound, GetCursorBounds()); | |
1651 | |
1652 SendKeyEvent(ui::VKEY_END); | |
1653 bound = GetCursorBounds(); | |
1654 MouseClick(bound, 10); | |
1655 EXPECT_EQ(bound, GetCursorBounds()); | |
1656 | |
1657 NonClientMouseClick(); | |
1658 | |
1659 // RTL-LTR string in LTR context. | |
1660 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab")); | |
1661 | |
1662 SendKeyEvent(ui::VKEY_HOME); | |
1663 bound = GetCursorBounds(); | |
1664 MouseClick(bound, 10); | |
1665 EXPECT_EQ(bound, GetCursorBounds()); | |
1666 | |
1667 SendKeyEvent(ui::VKEY_END); | |
1668 bound = GetCursorBounds(); | |
1669 MouseClick(bound, -10); | |
1670 EXPECT_EQ(bound, GetCursorBounds()); | |
1671 } | |
1672 | |
1673 TEST_F(NativeTextfieldViewsTest, HitOutsideTextAreaInRTLTest) { | |
1674 std::string locale = l10n_util::GetApplicationLocale(""); | |
1675 base::i18n::SetICUDefaultLocale("he"); | |
1676 | |
1677 InitTextfield(Textfield::STYLE_DEFAULT); | |
1678 | |
1679 // RTL-LTR string in RTL context. | |
1680 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab")); | |
1681 SendKeyEvent(ui::VKEY_HOME); | |
1682 gfx::Rect bound = GetCursorBounds(); | |
1683 MouseClick(bound, 10); | |
1684 EXPECT_EQ(bound, GetCursorBounds()); | |
1685 | |
1686 SendKeyEvent(ui::VKEY_END); | |
1687 bound = GetCursorBounds(); | |
1688 MouseClick(bound, -10); | |
1689 EXPECT_EQ(bound, GetCursorBounds()); | |
1690 | |
1691 NonClientMouseClick(); | |
1692 | |
1693 // LTR-RTL string in RTL context. | |
1694 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2")); | |
1695 SendKeyEvent(ui::VKEY_HOME); | |
1696 bound = GetCursorBounds(); | |
1697 MouseClick(bound, -10); | |
1698 EXPECT_EQ(bound, GetCursorBounds()); | |
1699 | |
1700 SendKeyEvent(ui::VKEY_END); | |
1701 bound = GetCursorBounds(); | |
1702 MouseClick(bound, 10); | |
1703 EXPECT_EQ(bound, GetCursorBounds()); | |
1704 | |
1705 // Reset locale. | |
1706 base::i18n::SetICUDefaultLocale(locale); | |
1707 } | |
1708 | |
1709 TEST_F(NativeTextfieldViewsTest, OverflowTest) { | |
1710 InitTextfield(Textfield::STYLE_DEFAULT); | |
1711 | |
1712 base::string16 str; | |
1713 for (int i = 0; i < 500; ++i) | |
1714 SendKeyEvent('a'); | |
1715 SendKeyEvent(kHebrewLetterSamekh); | |
1716 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds())); | |
1717 | |
1718 // Test mouse pointing. | |
1719 MouseClick(GetCursorBounds(), -1); | |
1720 EXPECT_EQ(500U, textfield_->GetCursorPosition()); | |
1721 | |
1722 // Clear text. | |
1723 SendKeyEvent(ui::VKEY_A, false, true); | |
1724 SendKeyEvent('\n'); | |
1725 | |
1726 for (int i = 0; i < 500; ++i) | |
1727 SendKeyEvent(kHebrewLetterSamekh); | |
1728 SendKeyEvent('a'); | |
1729 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds())); | |
1730 | |
1731 MouseClick(GetCursorBounds(), -1); | |
1732 EXPECT_EQ(501U, textfield_->GetCursorPosition()); | |
1733 } | |
1734 | |
1735 TEST_F(NativeTextfieldViewsTest, OverflowInRTLTest) { | |
1736 std::string locale = l10n_util::GetApplicationLocale(""); | |
1737 base::i18n::SetICUDefaultLocale("he"); | |
1738 | |
1739 InitTextfield(Textfield::STYLE_DEFAULT); | |
1740 | |
1741 base::string16 str; | |
1742 for (int i = 0; i < 500; ++i) | |
1743 SendKeyEvent('a'); | |
1744 SendKeyEvent(kHebrewLetterSamekh); | |
1745 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds())); | |
1746 | |
1747 MouseClick(GetCursorBounds(), 1); | |
1748 EXPECT_EQ(501U, textfield_->GetCursorPosition()); | |
1749 | |
1750 // Clear text. | |
1751 SendKeyEvent(ui::VKEY_A, false, true); | |
1752 SendKeyEvent('\n'); | |
1753 | |
1754 for (int i = 0; i < 500; ++i) | |
1755 SendKeyEvent(kHebrewLetterSamekh); | |
1756 SendKeyEvent('a'); | |
1757 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds())); | |
1758 | |
1759 MouseClick(GetCursorBounds(), 1); | |
1760 EXPECT_EQ(500U, textfield_->GetCursorPosition()); | |
1761 | |
1762 // Reset locale. | |
1763 base::i18n::SetICUDefaultLocale(locale); | |
1764 } | |
1765 | |
1766 TEST_F(NativeTextfieldViewsTest, GetCompositionCharacterBoundsTest) { | |
1767 InitTextfield(Textfield::STYLE_DEFAULT); | |
1768 | |
1769 base::string16 str; | |
1770 const uint32 char_count = 10UL; | |
1771 ui::CompositionText composition; | |
1772 composition.text = UTF8ToUTF16("0123456789"); | |
1773 ui::TextInputClient* client = textfield_->GetTextInputClient(); | |
1774 | |
1775 // Return false if there is no composition text. | |
1776 gfx::Rect rect; | |
1777 EXPECT_FALSE(client->GetCompositionCharacterBounds(0, &rect)); | |
1778 | |
1779 // Get each character boundary by cursor. | |
1780 gfx::Rect char_rect_in_screen_coord[char_count]; | |
1781 gfx::Rect prev_cursor = GetCursorBounds(); | |
1782 for (uint32 i = 0; i < char_count; ++i) { | |
1783 composition.selection = gfx::Range(0, i+1); | |
1784 client->SetCompositionText(composition); | |
1785 EXPECT_TRUE(client->HasCompositionText()) << " i=" << i; | |
1786 gfx::Rect cursor_bounds = GetCursorBounds(); | |
1787 gfx::Point top_left(prev_cursor.x(), prev_cursor.y()); | |
1788 gfx::Point bottom_right(cursor_bounds.x(), prev_cursor.bottom()); | |
1789 views::View::ConvertPointToScreen(textfield_view_, &top_left); | |
1790 views::View::ConvertPointToScreen(textfield_view_, &bottom_right); | |
1791 char_rect_in_screen_coord[i].set_origin(top_left); | |
1792 char_rect_in_screen_coord[i].set_width(bottom_right.x() - top_left.x()); | |
1793 char_rect_in_screen_coord[i].set_height(bottom_right.y() - top_left.y()); | |
1794 prev_cursor = cursor_bounds; | |
1795 } | |
1796 | |
1797 for (uint32 i = 0; i < char_count; ++i) { | |
1798 gfx::Rect actual_rect; | |
1799 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &actual_rect)) | |
1800 << " i=" << i; | |
1801 EXPECT_EQ(char_rect_in_screen_coord[i], actual_rect) << " i=" << i; | |
1802 } | |
1803 | |
1804 // Return false if the index is out of range. | |
1805 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count, &rect)); | |
1806 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 1, &rect)); | |
1807 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 100, &rect)); | |
1808 } | |
1809 | |
1810 TEST_F(NativeTextfieldViewsTest, GetCompositionCharacterBounds_ComplexText) { | |
1811 InitTextfield(Textfield::STYLE_DEFAULT); | |
1812 | |
1813 const base::char16 kUtf16Chars[] = { | |
1814 // U+0020 SPACE | |
1815 0x0020, | |
1816 // U+1F408 (CAT) as surrogate pair | |
1817 0xd83d, 0xdc08, | |
1818 // U+5642 as Ideographic Variation Sequences | |
1819 0x5642, 0xDB40, 0xDD00, | |
1820 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences | |
1821 0x260E, 0xFE0F, | |
1822 // U+0020 SPACE | |
1823 0x0020, | |
1824 }; | |
1825 const size_t kUtf16CharsCount = arraysize(kUtf16Chars); | |
1826 | |
1827 ui::CompositionText composition; | |
1828 composition.text.assign(kUtf16Chars, kUtf16Chars + kUtf16CharsCount); | |
1829 ui::TextInputClient* client = textfield_->GetTextInputClient(); | |
1830 client->SetCompositionText(composition); | |
1831 | |
1832 // Make sure GetCompositionCharacterBounds never fails for index. | |
1833 gfx::Rect rects[kUtf16CharsCount]; | |
1834 gfx::Rect prev_cursor = GetCursorBounds(); | |
1835 for (uint32 i = 0; i < kUtf16CharsCount; ++i) | |
1836 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &rects[i])); | |
1837 | |
1838 // Here we might expect the following results but it actually depends on how | |
1839 // Uniscribe or HarfBuzz treats them with given font. | |
1840 // - rects[1] == rects[2] | |
1841 // - rects[3] == rects[4] == rects[5] | |
1842 // - rects[6] == rects[7] | |
1843 } | |
1844 | |
1845 // The word we select by double clicking should remain selected regardless of | |
1846 // where we drag the mouse afterwards without releasing the left button. | |
1847 TEST_F(NativeTextfieldViewsTest, KeepInitiallySelectedWord) { | |
1848 InitTextfield(Textfield::STYLE_DEFAULT); | |
1849 | |
1850 textfield_->SetText(ASCIIToUTF16("abc def ghi")); | |
1851 | |
1852 textfield_->SelectRange(gfx::Range(5, 5)); | |
1853 const gfx::Rect middle_cursor = GetCursorBounds(); | |
1854 textfield_->SelectRange(gfx::Range(0, 0)); | |
1855 const gfx::Point beginning = GetCursorBounds().origin(); | |
1856 | |
1857 // Double click, but do not release the left button. | |
1858 MouseClick(middle_cursor, 0); | |
1859 const gfx::Point middle(middle_cursor.x(), | |
1860 middle_cursor.y() + middle_cursor.height() / 2); | |
1861 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, middle, middle, | |
1862 ui::EF_LEFT_MOUSE_BUTTON, | |
1863 ui::EF_LEFT_MOUSE_BUTTON); | |
1864 textfield_view_->OnMousePressed(press_event); | |
1865 EXPECT_EQ(gfx::Range(4, 7), textfield_->GetSelectedRange()); | |
1866 | |
1867 // Drag the mouse to the beginning of the textfield. | |
1868 ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, beginning, beginning, | |
1869 ui::EF_LEFT_MOUSE_BUTTON, 0); | |
1870 textfield_view_->OnMouseDragged(drag_event); | |
1871 EXPECT_EQ(gfx::Range(7, 0), textfield_->GetSelectedRange()); | |
1872 } | |
1873 | |
1874 // Touch selection and draggin currently only works for chromeos. | |
1875 #if defined(OS_CHROMEOS) | |
1876 TEST_F(NativeTextfieldViewsTest, TouchSelectionAndDraggingTest) { | |
1877 InitTextfield(Textfield::STYLE_DEFAULT); | |
1878 textfield_->SetText(ASCIIToUTF16("hello world")); | |
1879 EXPECT_FALSE(GetTouchSelectionController()); | |
1880 const int eventX = GetCursorPositionX(2); | |
1881 const int eventY = 0; | |
1882 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing); | |
1883 | |
1884 // Tapping on the textfield should turn on the TouchSelectionController. | |
1885 GestureEventForTest tap(ui::ET_GESTURE_TAP, eventX, eventY, 1.0f, 0.0f); | |
1886 textfield_view_->OnGestureEvent(&tap); | |
1887 EXPECT_TRUE(GetTouchSelectionController()); | |
1888 | |
1889 // Un-focusing the textfield should reset the TouchSelectionController | |
1890 textfield_view_->GetFocusManager()->ClearFocus(); | |
1891 EXPECT_FALSE(GetTouchSelectionController()); | |
1892 | |
1893 // With touch editing enabled, long press should not show context menu. | |
1894 // Instead, select word and invoke TouchSelectionController. | |
1895 GestureEventForTest tap_down(ui::ET_GESTURE_TAP_DOWN, eventX, eventY, 0.0f, | |
1896 0.0f); | |
1897 textfield_view_->OnGestureEvent(&tap_down); | |
1898 GestureEventForTest long_press(ui::ET_GESTURE_LONG_PRESS, eventX, eventY, | |
1899 0.0f, 0.0f); | |
1900 textfield_view_->OnGestureEvent(&long_press); | |
1901 EXPECT_STR_EQ("hello", textfield_->GetSelectedText()); | |
1902 EXPECT_TRUE(GetTouchSelectionController()); | |
1903 | |
1904 // Long pressing again in the selecting region should not do anything since | |
1905 // touch drag drop is not yet enabled. | |
1906 textfield_view_->OnGestureEvent(&tap_down); | |
1907 textfield_view_->OnGestureEvent(&long_press); | |
1908 EXPECT_STR_EQ("hello", textfield_->GetSelectedText()); | |
1909 EXPECT_TRUE(GetTouchSelectionController()); | |
1910 EXPECT_TRUE(long_press.handled()); | |
1911 | |
1912 // After enabling touch drag drop, long pressing in the selected region should | |
1913 // start a drag and remove TouchSelectionController. | |
1914 CommandLine::ForCurrentProcess()->AppendSwitch( | |
1915 switches::kEnableTouchDragDrop); | |
1916 textfield_view_->OnGestureEvent(&tap_down); | |
1917 | |
1918 // Create a new long press event since the previous one is not marked handled. | |
1919 GestureEventForTest long_press2(ui::ET_GESTURE_LONG_PRESS, eventX, eventY, | |
1920 0.0f, 0.0f); | |
1921 textfield_view_->OnGestureEvent(&long_press2); | |
1922 EXPECT_STR_EQ("hello", textfield_->GetSelectedText()); | |
1923 EXPECT_FALSE(GetTouchSelectionController()); | |
1924 } | |
1925 | |
1926 TEST_F(NativeTextfieldViewsTest, TouchScrubbingSelection) { | |
1927 InitTextfield(Textfield::STYLE_DEFAULT); | |
1928 textfield_->SetText(ASCIIToUTF16("hello world")); | |
1929 EXPECT_FALSE(GetTouchSelectionController()); | |
1930 | |
1931 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing); | |
1932 | |
1933 // Simulate touch-scrubbing. | |
1934 int scrubbing_start = GetCursorPositionX(1); | |
1935 int scrubbing_end = GetCursorPositionX(6); | |
1936 | |
1937 GestureEventForTest tap_down(ui::ET_GESTURE_TAP_DOWN, scrubbing_start, 0, | |
1938 0.0f, 0.0f); | |
1939 textfield_view_->OnGestureEvent(&tap_down); | |
1940 | |
1941 GestureEventForTest tap_cancel(ui::ET_GESTURE_TAP_CANCEL, scrubbing_start, 0, | |
1942 0.0f, 0.0f); | |
1943 textfield_view_->OnGestureEvent(&tap_cancel); | |
1944 | |
1945 GestureEventForTest scroll_begin(ui::ET_GESTURE_SCROLL_BEGIN, scrubbing_start, | |
1946 0, 0.0f, 0.0f); | |
1947 textfield_view_->OnGestureEvent(&scroll_begin); | |
1948 | |
1949 GestureEventForTest scroll_update(ui::ET_GESTURE_SCROLL_UPDATE, scrubbing_end, | |
1950 0, scrubbing_end - scrubbing_start, 0.0f); | |
1951 textfield_view_->OnGestureEvent(&scroll_update); | |
1952 | |
1953 GestureEventForTest scroll_end(ui::ET_GESTURE_SCROLL_END, scrubbing_end, 0, | |
1954 0.0f, 0.0f); | |
1955 textfield_view_->OnGestureEvent(&scroll_end); | |
1956 | |
1957 GestureEventForTest end(ui::ET_GESTURE_END, scrubbing_end, 0, 0.0f, 0.0f); | |
1958 textfield_view_->OnGestureEvent(&end); | |
1959 | |
1960 // In the end, part of text should have been selected and handles should have | |
1961 // appeared. | |
1962 EXPECT_STR_EQ("ello ", textfield_->GetSelectedText()); | |
1963 EXPECT_TRUE(GetTouchSelectionController()); | |
1964 } | |
1965 #endif | |
1966 | |
1967 // Long_Press gesture in NativeTextfieldViews can initiate a drag and drop now. | |
1968 TEST_F(NativeTextfieldViewsTest, TestLongPressInitiatesDragDrop) { | |
1969 InitTextfield(Textfield::STYLE_DEFAULT); | |
1970 textfield_->SetText(ASCIIToUTF16("Hello string world")); | |
1971 | |
1972 // Ensure the textfield will provide selected text for drag data. | |
1973 textfield_->SelectRange(gfx::Range(6, 12)); | |
1974 const gfx::Point kStringPoint(GetCursorPositionX(9), 0); | |
1975 | |
1976 // Enable touch-drag-drop to make long press effective. | |
1977 CommandLine::ForCurrentProcess()->AppendSwitch( | |
1978 switches::kEnableTouchDragDrop); | |
1979 | |
1980 // Create a long press event in the selected region should start a drag. | |
1981 GestureEventForTest long_press(ui::ET_GESTURE_LONG_PRESS, kStringPoint.x(), | |
1982 kStringPoint.y(), 0.0f, 0.0f); | |
1983 textfield_view_->OnGestureEvent(&long_press); | |
1984 EXPECT_TRUE(textfield_view_->CanStartDragForView(NULL, | |
1985 kStringPoint, kStringPoint)); | |
1986 } | |
1987 | |
1988 TEST_F(NativeTextfieldViewsTest, GetTextfieldBaseline_FontFallbackTest) { | |
1989 InitTextfield(Textfield::STYLE_DEFAULT); | |
1990 textfield_->SetText(UTF8ToUTF16("abc")); | |
1991 const int old_baseline = textfield_->GetBaseline(); | |
1992 | |
1993 // Set text which may fall back to a font which has taller baseline than | |
1994 // the default font. | |
1995 textfield_->SetText(UTF8ToUTF16("\xE0\xB9\x91")); | |
1996 const int new_baseline = textfield_->GetBaseline(); | |
1997 | |
1998 // Regardless of the text, the baseline must be the same. | |
1999 EXPECT_EQ(new_baseline, old_baseline); | |
2000 } | |
2001 | |
2002 } // namespace views | |
OLD | NEW |