MacViews: Convert Cocoa action messages into editing commands for text fields
[chromium-blink-merge.git] / ui / views / controls / textfield / textfield_unittest.cc
blob2cbd7de6968816093c99d8ba205784367265cfe5
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.
5 #include "ui/views/controls/textfield/textfield.h"
7 #include <set>
8 #include <string>
9 #include <vector>
11 #include "base/command_line.h"
12 #include "base/pickle.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "ui/base/clipboard/clipboard.h"
16 #include "ui/base/clipboard/scoped_clipboard_writer.h"
17 #include "ui/base/dragdrop/drag_drop_types.h"
18 #include "ui/base/ime/text_input_client.h"
19 #include "ui/base/l10n/l10n_util.h"
20 #include "ui/base/ui_base_switches.h"
21 #include "ui/base/ui_base_switches_util.h"
22 #include "ui/events/event.h"
23 #include "ui/events/keycodes/keyboard_codes.h"
24 #include "ui/events/test/event_generator.h"
25 #include "ui/gfx/render_text.h"
26 #include "ui/strings/grit/ui_strings.h"
27 #include "ui/views/controls/textfield/textfield_controller.h"
28 #include "ui/views/controls/textfield/textfield_model.h"
29 #include "ui/views/controls/textfield/textfield_test_api.h"
30 #include "ui/views/focus/focus_manager.h"
31 #include "ui/views/ime/mock_input_method.h"
32 #include "ui/views/test/test_views_delegate.h"
33 #include "ui/views/test/views_test_base.h"
34 #include "ui/views/test/widget_test.h"
35 #include "ui/views/widget/widget.h"
36 #include "url/gurl.h"
38 #if defined(OS_WIN)
39 #include "base/win/windows_version.h"
40 #endif
42 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
43 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
44 #endif
46 #if defined(USE_X11)
47 #include "ui/events/event_utils.h"
48 #endif
50 using base::ASCIIToUTF16;
51 using base::UTF8ToUTF16;
52 using base::WideToUTF16;
54 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
56 namespace {
58 const base::char16 kHebrewLetterSamekh = 0x05E1;
60 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
61 class TestTextfield : public views::Textfield {
62 public:
63 TestTextfield()
64 : Textfield(),
65 key_handled_(false),
66 key_received_(false),
67 weak_ptr_factory_(this) {}
69 bool OnKeyPressed(const ui::KeyEvent& e) override {
70 key_received_ = true;
72 // Since OnKeyPressed() might destroy |this|, get a weak pointer and
73 // verify it isn't null before writing the bool value to key_handled_.
74 base::WeakPtr<TestTextfield> textfield(weak_ptr_factory_.GetWeakPtr());
75 bool key = views::Textfield::OnKeyPressed(e);
77 if (!textfield)
78 return key;
80 key_handled_ = key;
82 return key_handled_;
85 bool OnKeyReleased(const ui::KeyEvent& e) override {
86 key_received_ = true;
87 key_handled_ = views::Textfield::OnKeyReleased(e);
88 return key_handled_;
91 bool key_handled() const { return key_handled_; }
92 bool key_received() const { return key_received_; }
94 void clear() { key_received_ = key_handled_ = false; }
96 private:
97 bool key_handled_;
98 bool key_received_;
100 base::WeakPtrFactory<TestTextfield> weak_ptr_factory_;
102 DISALLOW_COPY_AND_ASSIGN(TestTextfield);
105 // Convenience to make constructing a GestureEvent simpler.
106 class GestureEventForTest : public ui::GestureEvent {
107 public:
108 GestureEventForTest(int x, int y, ui::GestureEventDetails details)
109 : GestureEvent(x, y, 0, base::TimeDelta(), details) {}
111 private:
112 DISALLOW_COPY_AND_ASSIGN(GestureEventForTest);
115 // This controller will happily destroy the target textfield passed on
116 // construction when a key event is triggered.
117 class TextfieldDestroyerController : public views::TextfieldController {
118 public:
119 explicit TextfieldDestroyerController(views::Textfield* target)
120 : target_(target) {
121 target_->set_controller(this);
124 views::Textfield* target() { return target_.get(); }
126 // views::TextfieldController:
127 bool HandleKeyEvent(views::Textfield* sender,
128 const ui::KeyEvent& key_event) override {
129 target_.reset();
130 return false;
133 private:
134 scoped_ptr<views::Textfield> target_;
137 base::string16 GetClipboardText(ui::ClipboardType type) {
138 base::string16 text;
139 ui::Clipboard::GetForCurrentThread()->ReadText(type, &text);
140 return text;
143 void SetClipboardText(ui::ClipboardType type, const std::string& text) {
144 ui::ScopedClipboardWriter(type).WriteText(ASCIIToUTF16(text));
147 } // namespace
149 namespace views {
151 class TextfieldTest : public ViewsTestBase, public TextfieldController {
152 public:
153 TextfieldTest()
154 : widget_(NULL),
155 textfield_(NULL),
156 model_(NULL),
157 input_method_(NULL),
158 on_before_user_action_(0),
159 on_after_user_action_(0),
160 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) {
163 // ::testing::Test:
164 void TearDown() override {
165 if (widget_)
166 widget_->Close();
167 ViewsTestBase::TearDown();
170 ui::ClipboardType GetAndResetCopiedToClipboard() {
171 ui::ClipboardType clipboard_type = copied_to_clipboard_;
172 copied_to_clipboard_ = ui::CLIPBOARD_TYPE_LAST;
173 return clipboard_type;
176 // TextfieldController:
177 void ContentsChanged(Textfield* sender,
178 const base::string16& new_contents) override {
179 // Paste calls TextfieldController::ContentsChanged() explicitly even if the
180 // paste action did not change the content. So |new_contents| may match
181 // |last_contents_|. For more info, see http://crbug.com/79002
182 last_contents_ = new_contents;
185 void OnBeforeUserAction(Textfield* sender) override {
186 ++on_before_user_action_;
189 void OnAfterUserAction(Textfield* sender) override {
190 ++on_after_user_action_;
193 void OnAfterCutOrCopy(ui::ClipboardType clipboard_type) override {
194 copied_to_clipboard_ = clipboard_type;
197 void InitTextfield() {
198 InitTextfields(1);
201 void InitTextfields(int count) {
202 ASSERT_FALSE(textfield_);
203 textfield_ = new TestTextfield();
204 textfield_->set_controller(this);
205 widget_ = new Widget();
207 // The widget type must be an activatable type, and we don't want to worry
208 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS.
209 Widget::InitParams params =
210 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
212 params.bounds = gfx::Rect(100, 100, 100, 100);
213 widget_->Init(params);
214 View* container = new View();
215 widget_->SetContentsView(container);
216 container->AddChildView(textfield_);
217 textfield_->SetBoundsRect(params.bounds);
218 textfield_->set_id(1);
219 test_api_.reset(new TextfieldTestApi(textfield_));
221 for (int i = 1; i < count; i++) {
222 Textfield* textfield = new Textfield();
223 container->AddChildView(textfield);
224 textfield->set_id(i + 1);
227 model_ = test_api_->model();
228 model_->ClearEditHistory();
230 input_method_ = new MockInputMethod();
231 widget_->ReplaceInputMethod(input_method_);
233 // Since the window type is activatable, showing the widget will also
234 // activate it. Calling Activate directly is insufficient, since that does
235 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the
236 // widget and the textfield must have focus to properly handle input.
237 widget_->Show();
238 textfield_->RequestFocus();
240 // On Mac, activation is asynchronous since desktop widgets are used. We
241 // don't want parallel tests to steal active status either, so fake it.
242 #if defined(OS_MACOSX) && !defined(USE_AURA)
243 fake_activation_ = test::WidgetTest::FakeWidgetIsActiveAlways();
244 #endif
246 event_generator_.reset(
247 new ui::test::EventGenerator(GetContext(), widget_->GetNativeWindow()));
250 ui::MenuModel* GetContextMenuModel() {
251 test_api_->UpdateContextMenu();
252 return test_api_->context_menu_contents();
255 // True if native Mac keystrokes should be used (to avoid ifdef litter).
256 bool TestingNativeMac() {
257 #if defined(OS_MACOSX)
258 return true;
259 #else
260 return false;
261 #endif
264 protected:
265 void SendKeyEvent(ui::KeyboardCode key_code,
266 bool alt,
267 bool shift,
268 bool control_or_command,
269 bool caps_lock) {
270 bool control = control_or_command;
271 bool command = false;
273 // By default, swap control and command for native events on Mac. This
274 // handles most cases.
275 if (TestingNativeMac())
276 std::swap(control, command);
278 int flags = (alt ? ui::EF_ALT_DOWN : 0) | (shift ? ui::EF_SHIFT_DOWN : 0) |
279 (control ? ui::EF_CONTROL_DOWN : 0) |
280 (command ? ui::EF_COMMAND_DOWN : 0) |
281 (caps_lock ? ui::EF_CAPS_LOCK_DOWN : 0);
283 event_generator_->PressKey(key_code, flags);
286 void SendKeyEvent(ui::KeyboardCode key_code,
287 bool shift,
288 bool control_or_command) {
289 SendKeyEvent(key_code, false, shift, control_or_command, false);
292 void SendKeyEvent(ui::KeyboardCode key_code) {
293 SendKeyEvent(key_code, false, false);
296 void SendKeyEvent(base::char16 ch) {
297 if (ch < 0x80) {
298 ui::KeyboardCode code =
299 ch == ' ' ? ui::VKEY_SPACE :
300 static_cast<ui::KeyboardCode>(ui::VKEY_A + ch - 'a');
301 SendKeyEvent(code);
302 } else {
303 // For unicode characters, assume they come from IME rather than the
304 // keyboard. So they are dispatched directly to the input method.
305 ui::KeyEvent event(ch, ui::VKEY_UNKNOWN, ui::EF_NONE);
306 input_method_->DispatchKeyEvent(event);
310 // Sends a platform-specific move (and select) to start of line.
311 void SendHomeEvent(bool shift) {
312 if (TestingNativeMac()) {
313 // Use Cmd+Left on native Mac. An RTL-agnostic "end" doesn't have a
314 // default key-binding on Mac.
315 SendKeyEvent(ui::VKEY_LEFT, shift /* shift */, true /* command */);
316 return;
318 SendKeyEvent(ui::VKEY_HOME, shift /* shift */, false /* control */);
321 // Sends a platform-specific move (and select) to end of line.
322 void SendEndEvent(bool shift) {
323 if (TestingNativeMac()) {
324 SendKeyEvent(ui::VKEY_RIGHT, shift, true); // Cmd+Right.
325 return;
327 SendKeyEvent(ui::VKEY_END, shift, false);
330 // Sends {delete, move, select} word {forward, backward}.
331 void SendWordEvent(ui::KeyboardCode key, bool shift) {
332 bool alt = false;
333 bool control = true;
334 bool caps = false;
335 if (TestingNativeMac()) {
336 // Use Alt+Left/Right/Backspace on native Mac.
337 alt = true;
338 control = false;
340 SendKeyEvent(key, alt, shift, control, caps);
343 View* GetFocusedView() {
344 return widget_->GetFocusManager()->GetFocusedView();
347 int GetCursorPositionX(int cursor_pos) {
348 return test_api_->GetRenderText()->GetCursorBounds(
349 gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), false).x();
352 // Get the current cursor bounds.
353 gfx::Rect GetCursorBounds() {
354 return test_api_->GetRenderText()->GetUpdatedCursorBounds();
357 // Get the cursor bounds of |sel|.
358 gfx::Rect GetCursorBounds(const gfx::SelectionModel& sel) {
359 return test_api_->GetRenderText()->GetCursorBounds(sel, true);
362 gfx::Rect GetDisplayRect() {
363 return test_api_->GetRenderText()->display_rect();
366 // Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and
367 // y-axis is in the middle of |bound|'s vertical range.
368 void MouseClick(const gfx::Rect bound, int x_offset) {
369 gfx::Point point(bound.x() + x_offset, bound.y() + bound.height() / 2);
370 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
371 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
372 textfield_->OnMousePressed(click);
373 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point, point,
374 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
375 textfield_->OnMouseReleased(release);
378 // This is to avoid double/triple click.
379 void NonClientMouseClick() {
380 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
381 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT,
382 ui::EF_LEFT_MOUSE_BUTTON);
383 textfield_->OnMousePressed(click);
384 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
385 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT,
386 ui::EF_LEFT_MOUSE_BUTTON);
387 textfield_->OnMouseReleased(release);
390 void VerifyTextfieldContextMenuContents(bool textfield_has_selection,
391 bool can_undo,
392 ui::MenuModel* menu) {
393 EXPECT_EQ(can_undo, menu->IsEnabledAt(0 /* UNDO */));
394 EXPECT_TRUE(menu->IsEnabledAt(1 /* Separator */));
395 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(2 /* CUT */));
396 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(3 /* COPY */));
397 EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE).empty(),
398 menu->IsEnabledAt(4 /* PASTE */));
399 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(5 /* DELETE */));
400 EXPECT_TRUE(menu->IsEnabledAt(6 /* Separator */));
401 EXPECT_TRUE(menu->IsEnabledAt(7 /* SELECT ALL */));
404 // We need widget to populate wrapper class.
405 Widget* widget_;
407 TestTextfield* textfield_;
408 scoped_ptr<TextfieldTestApi> test_api_;
409 TextfieldModel* model_;
411 // The string from Controller::ContentsChanged callback.
412 base::string16 last_contents_;
414 // For testing input method related behaviors.
415 MockInputMethod* input_method_;
417 // Indicates how many times OnBeforeUserAction() is called.
418 int on_before_user_action_;
420 // Indicates how many times OnAfterUserAction() is called.
421 int on_after_user_action_;
423 private:
424 ui::ClipboardType copied_to_clipboard_;
425 scoped_ptr<test::WidgetTest::FakeActivation> fake_activation_;
426 scoped_ptr<ui::test::EventGenerator> event_generator_;
428 DISALLOW_COPY_AND_ASSIGN(TextfieldTest);
431 TEST_F(TextfieldTest, ModelChangesTest) {
432 InitTextfield();
434 // TextfieldController::ContentsChanged() shouldn't be called when changing
435 // text programmatically.
436 last_contents_.clear();
437 textfield_->SetText(ASCIIToUTF16("this is"));
439 EXPECT_STR_EQ("this is", model_->text());
440 EXPECT_STR_EQ("this is", textfield_->text());
441 EXPECT_TRUE(last_contents_.empty());
443 textfield_->AppendText(ASCIIToUTF16(" a test"));
444 EXPECT_STR_EQ("this is a test", model_->text());
445 EXPECT_STR_EQ("this is a test", textfield_->text());
446 EXPECT_TRUE(last_contents_.empty());
448 EXPECT_EQ(base::string16(), textfield_->GetSelectedText());
449 textfield_->SelectAll(false);
450 EXPECT_STR_EQ("this is a test", textfield_->GetSelectedText());
451 EXPECT_TRUE(last_contents_.empty());
454 TEST_F(TextfieldTest, KeyTest) {
455 InitTextfield();
456 // Event flags: key, alt, shift, ctrl, caps-lock.
457 SendKeyEvent(ui::VKEY_T, false, true, false, false);
458 SendKeyEvent(ui::VKEY_E, false, false, false, false);
459 SendKeyEvent(ui::VKEY_X, false, true, false, true);
460 SendKeyEvent(ui::VKEY_T, false, false, false, true);
461 SendKeyEvent(ui::VKEY_1, false, true, false, false);
462 SendKeyEvent(ui::VKEY_1, false, false, false, false);
463 SendKeyEvent(ui::VKEY_1, false, true, false, true);
464 SendKeyEvent(ui::VKEY_1, false, false, false, true);
465 EXPECT_STR_EQ("TexT!1!1", textfield_->text());
468 TEST_F(TextfieldTest, ControlAndSelectTest) {
469 // Insert a test string in a textfield.
470 InitTextfield();
471 textfield_->SetText(ASCIIToUTF16("one two three"));
472 SendHomeEvent(false);
473 SendKeyEvent(ui::VKEY_RIGHT, true, false);
474 SendKeyEvent(ui::VKEY_RIGHT, true, false);
475 SendKeyEvent(ui::VKEY_RIGHT, true, false);
477 EXPECT_STR_EQ("one", textfield_->GetSelectedText());
479 // Test word select.
480 SendWordEvent(ui::VKEY_RIGHT, true);
481 EXPECT_STR_EQ("one two", textfield_->GetSelectedText());
482 SendWordEvent(ui::VKEY_RIGHT, true);
483 EXPECT_STR_EQ("one two three", textfield_->GetSelectedText());
484 SendWordEvent(ui::VKEY_LEFT, true);
485 EXPECT_STR_EQ("one two ", textfield_->GetSelectedText());
486 SendWordEvent(ui::VKEY_LEFT, true);
487 EXPECT_STR_EQ("one ", textfield_->GetSelectedText());
489 // Replace the selected text.
490 SendKeyEvent(ui::VKEY_Z, true, false);
491 SendKeyEvent(ui::VKEY_E, true, false);
492 SendKeyEvent(ui::VKEY_R, true, false);
493 SendKeyEvent(ui::VKEY_O, true, false);
494 SendKeyEvent(ui::VKEY_SPACE, false, false);
495 EXPECT_STR_EQ("ZERO two three", textfield_->text());
497 SendEndEvent(true);
498 EXPECT_STR_EQ("two three", textfield_->GetSelectedText());
499 SendHomeEvent(true);
500 EXPECT_STR_EQ("ZERO ", textfield_->GetSelectedText());
503 TEST_F(TextfieldTest, InsertionDeletionTest) {
504 // Insert a test string in a textfield.
505 InitTextfield();
506 for (size_t i = 0; i < 10; i++)
507 SendKeyEvent(static_cast<ui::KeyboardCode>(ui::VKEY_A + i));
508 EXPECT_STR_EQ("abcdefghij", textfield_->text());
510 // Test the delete and backspace keys.
511 textfield_->SelectRange(gfx::Range(5));
512 for (int i = 0; i < 3; i++)
513 SendKeyEvent(ui::VKEY_BACK);
514 EXPECT_STR_EQ("abfghij", textfield_->text());
515 for (int i = 0; i < 3; i++)
516 SendKeyEvent(ui::VKEY_DELETE);
517 EXPECT_STR_EQ("abij", textfield_->text());
519 // Select all and replace with "k".
520 textfield_->SelectAll(false);
521 SendKeyEvent(ui::VKEY_K);
522 EXPECT_STR_EQ("k", textfield_->text());
524 // Delete the previous word from cursor.
525 bool shift = false;
526 textfield_->SetText(ASCIIToUTF16("one two three four"));
527 SendEndEvent(shift);
528 SendWordEvent(ui::VKEY_BACK, shift);
529 EXPECT_STR_EQ("one two three ", textfield_->text());
531 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
532 // and Mac.
533 SendWordEvent(ui::VKEY_LEFT, shift);
534 shift = true;
535 SendWordEvent(ui::VKEY_BACK, shift);
536 #if defined(OS_LINUX)
537 EXPECT_STR_EQ("three ", textfield_->text());
538 #else
539 EXPECT_STR_EQ("one three ", textfield_->text());
540 #endif
542 // Delete the next word from cursor.
543 textfield_->SetText(ASCIIToUTF16("one two three four"));
544 shift = false;
545 SendHomeEvent(shift);
546 SendWordEvent(ui::VKEY_DELETE, shift);
547 EXPECT_STR_EQ(" two three four", textfield_->text());
549 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
550 // and Mac.
551 SendWordEvent(ui::VKEY_RIGHT, shift);
552 shift = true;
553 SendWordEvent(ui::VKEY_DELETE, shift);
554 #if defined(OS_LINUX)
555 EXPECT_STR_EQ(" two", textfield_->text());
556 #else
557 EXPECT_STR_EQ(" two four", textfield_->text());
558 #endif
561 TEST_F(TextfieldTest, PasswordTest) {
562 InitTextfield();
563 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
564 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
565 EXPECT_TRUE(textfield_->enabled());
566 EXPECT_TRUE(textfield_->IsFocusable());
568 last_contents_.clear();
569 textfield_->SetText(ASCIIToUTF16("password"));
570 // Ensure text() and the callback returns the actual text instead of "*".
571 EXPECT_STR_EQ("password", textfield_->text());
572 EXPECT_TRUE(last_contents_.empty());
573 model_->SelectAll(false);
574 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
576 // Cut and copy should be disabled.
577 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
578 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
579 SendKeyEvent(ui::VKEY_X, false, true);
580 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
581 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
582 SendKeyEvent(ui::VKEY_C, false, true);
583 SendKeyEvent(ui::VKEY_INSERT, false, true);
584 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
585 EXPECT_STR_EQ("password", textfield_->text());
586 // [Shift]+[Delete] should just delete without copying text to the clipboard.
587 textfield_->SelectAll(false);
588 SendKeyEvent(ui::VKEY_DELETE, true, false);
590 // Paste should work normally.
591 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
592 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
593 SendKeyEvent(ui::VKEY_V, false, true);
594 SendKeyEvent(ui::VKEY_INSERT, true, false);
595 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
596 EXPECT_STR_EQ("foofoofoo", textfield_->text());
599 TEST_F(TextfieldTest, TextInputType) {
600 InitTextfield();
602 // Defaults to TEXT
603 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, textfield_->GetTextInputType());
605 // And can be set.
606 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_URL);
607 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, textfield_->GetTextInputType());
608 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
609 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
611 // Readonly textfields have type NONE
612 textfield_->SetReadOnly(true);
613 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
615 textfield_->SetReadOnly(false);
616 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
618 // As do disabled textfields
619 textfield_->SetEnabled(false);
620 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
622 textfield_->SetEnabled(true);
623 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
626 TEST_F(TextfieldTest, OnKeyPress) {
627 InitTextfield();
629 // Character keys are handled by the input method.
630 SendKeyEvent(ui::VKEY_A);
631 EXPECT_TRUE(textfield_->key_received());
632 EXPECT_FALSE(textfield_->key_handled());
633 textfield_->clear();
635 // Arrow keys and home/end are handled by the textfield.
636 SendKeyEvent(ui::VKEY_LEFT);
637 EXPECT_TRUE(textfield_->key_received());
638 EXPECT_TRUE(textfield_->key_handled());
639 textfield_->clear();
641 SendKeyEvent(ui::VKEY_RIGHT);
642 EXPECT_TRUE(textfield_->key_received());
643 EXPECT_TRUE(textfield_->key_handled());
644 textfield_->clear();
646 SendKeyEvent(ui::VKEY_HOME);
647 EXPECT_TRUE(textfield_->key_received());
648 EXPECT_TRUE(textfield_->key_handled());
649 textfield_->clear();
651 SendKeyEvent(ui::VKEY_END);
652 EXPECT_TRUE(textfield_->key_received());
653 EXPECT_TRUE(textfield_->key_handled());
654 textfield_->clear();
656 // F24, up/down key won't be handled.
657 SendKeyEvent(ui::VKEY_F24);
658 EXPECT_TRUE(textfield_->key_received());
659 EXPECT_FALSE(textfield_->key_handled());
660 textfield_->clear();
662 SendKeyEvent(ui::VKEY_UP);
663 EXPECT_TRUE(textfield_->key_received());
664 EXPECT_FALSE(textfield_->key_handled());
665 textfield_->clear();
667 SendKeyEvent(ui::VKEY_DOWN);
668 EXPECT_TRUE(textfield_->key_received());
669 EXPECT_FALSE(textfield_->key_handled());
670 textfield_->clear();
673 // Tests that default key bindings are handled even with a delegate installed.
674 TEST_F(TextfieldTest, OnKeyPressBinding) {
675 InitTextfield();
677 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
678 // Install a TextEditKeyBindingsDelegateAuraLinux that does nothing.
679 class TestDelegate : public ui::TextEditKeyBindingsDelegateAuraLinux {
680 public:
681 TestDelegate() {}
682 ~TestDelegate() override {}
684 bool MatchEvent(
685 const ui::Event& event,
686 std::vector<ui::TextEditCommandAuraLinux>* commands) override {
687 return false;
690 private:
691 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
694 TestDelegate delegate;
695 ui::SetTextEditKeyBindingsDelegate(&delegate);
696 #endif
698 SendKeyEvent(ui::VKEY_A, false, false);
699 EXPECT_STR_EQ("a", textfield_->text());
700 textfield_->clear();
702 // Undo/Redo command keys are handled by the textfield.
703 SendKeyEvent(ui::VKEY_Z, false, true);
704 EXPECT_TRUE(textfield_->key_received());
705 EXPECT_TRUE(textfield_->key_handled());
706 EXPECT_TRUE(textfield_->text().empty());
707 textfield_->clear();
709 SendKeyEvent(ui::VKEY_Z, true, true);
710 EXPECT_TRUE(textfield_->key_received());
711 EXPECT_TRUE(textfield_->key_handled());
712 EXPECT_STR_EQ("a", textfield_->text());
713 textfield_->clear();
715 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
716 ui::SetTextEditKeyBindingsDelegate(NULL);
717 #endif
720 TEST_F(TextfieldTest, CursorMovement) {
721 InitTextfield();
723 // Test with trailing whitespace.
724 textfield_->SetText(ASCIIToUTF16("one two hre "));
726 // Send the cursor at the end.
727 SendKeyEvent(ui::VKEY_END);
729 // Ctrl+Left should move the cursor just before the last word.
730 SendKeyEvent(ui::VKEY_LEFT, false, true);
731 SendKeyEvent(ui::VKEY_T);
732 EXPECT_STR_EQ("one two thre ", textfield_->text());
733 EXPECT_STR_EQ("one two thre ", last_contents_);
735 // Ctrl+Right should move the cursor to the end of the last word.
736 SendKeyEvent(ui::VKEY_RIGHT, false, true);
737 SendKeyEvent(ui::VKEY_E);
738 EXPECT_STR_EQ("one two three ", textfield_->text());
739 EXPECT_STR_EQ("one two three ", last_contents_);
741 // Ctrl+Right again should move the cursor to the end.
742 SendKeyEvent(ui::VKEY_RIGHT, false, true);
743 SendKeyEvent(ui::VKEY_BACK);
744 EXPECT_STR_EQ("one two three", textfield_->text());
745 EXPECT_STR_EQ("one two three", last_contents_);
747 // Test with leading whitespace.
748 textfield_->SetText(ASCIIToUTF16(" ne two"));
750 // Send the cursor at the beginning.
751 SendKeyEvent(ui::VKEY_HOME);
753 // Ctrl+Right, then Ctrl+Left should move the cursor to the beginning of the
754 // first word.
755 SendKeyEvent(ui::VKEY_RIGHT, false, true);
756 SendKeyEvent(ui::VKEY_LEFT, false, true);
757 SendKeyEvent(ui::VKEY_O);
758 EXPECT_STR_EQ(" one two", textfield_->text());
759 EXPECT_STR_EQ(" one two", last_contents_);
761 // Ctrl+Left to move the cursor to the beginning of the first word.
762 SendKeyEvent(ui::VKEY_LEFT, false, true);
763 // Ctrl+Left again should move the cursor back to the very beginning.
764 SendKeyEvent(ui::VKEY_LEFT, false, true);
765 SendKeyEvent(ui::VKEY_DELETE);
766 EXPECT_STR_EQ("one two", textfield_->text());
767 EXPECT_STR_EQ("one two", last_contents_);
770 TEST_F(TextfieldTest, FocusTraversalTest) {
771 InitTextfields(3);
772 textfield_->RequestFocus();
774 EXPECT_EQ(1, GetFocusedView()->id());
775 widget_->GetFocusManager()->AdvanceFocus(false);
776 EXPECT_EQ(2, GetFocusedView()->id());
777 widget_->GetFocusManager()->AdvanceFocus(false);
778 EXPECT_EQ(3, GetFocusedView()->id());
779 // Cycle back to the first textfield.
780 widget_->GetFocusManager()->AdvanceFocus(false);
781 EXPECT_EQ(1, GetFocusedView()->id());
783 widget_->GetFocusManager()->AdvanceFocus(true);
784 EXPECT_EQ(3, GetFocusedView()->id());
785 widget_->GetFocusManager()->AdvanceFocus(true);
786 EXPECT_EQ(2, GetFocusedView()->id());
787 widget_->GetFocusManager()->AdvanceFocus(true);
788 EXPECT_EQ(1, GetFocusedView()->id());
789 // Cycle back to the last textfield.
790 widget_->GetFocusManager()->AdvanceFocus(true);
791 EXPECT_EQ(3, GetFocusedView()->id());
793 // Request focus should still work.
794 textfield_->RequestFocus();
795 EXPECT_EQ(1, GetFocusedView()->id());
797 // Test if clicking on textfield view sets the focus.
798 widget_->GetFocusManager()->AdvanceFocus(true);
799 EXPECT_EQ(3, GetFocusedView()->id());
800 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
801 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
802 textfield_->OnMousePressed(click);
803 EXPECT_EQ(1, GetFocusedView()->id());
806 TEST_F(TextfieldTest, ContextMenuDisplayTest) {
807 InitTextfield();
808 EXPECT_TRUE(textfield_->context_menu_controller());
809 textfield_->SetText(ASCIIToUTF16("hello world"));
810 ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
811 textfield_->ClearEditHistory();
812 EXPECT_TRUE(GetContextMenuModel());
813 VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
815 textfield_->SelectAll(false);
816 VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel());
818 SendKeyEvent(ui::VKEY_T);
819 VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel());
821 textfield_->SelectAll(false);
822 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
824 // Exercise the "paste enabled?" check in the verifier.
825 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
826 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
829 TEST_F(TextfieldTest, DoubleAndTripleClickTest) {
830 InitTextfield();
831 textfield_->SetText(ASCIIToUTF16("hello world"));
832 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
833 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
834 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
835 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
836 ui::MouseEvent double_click(
837 ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
838 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
839 ui::EF_LEFT_MOUSE_BUTTON);
841 // Test for double click.
842 textfield_->OnMousePressed(click);
843 textfield_->OnMouseReleased(release);
844 EXPECT_TRUE(textfield_->GetSelectedText().empty());
845 textfield_->OnMousePressed(double_click);
846 textfield_->OnMouseReleased(release);
847 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
849 // Test for triple click.
850 textfield_->OnMousePressed(click);
851 textfield_->OnMouseReleased(release);
852 EXPECT_STR_EQ("hello world", textfield_->GetSelectedText());
854 // Another click should reset back to double click.
855 textfield_->OnMousePressed(click);
856 textfield_->OnMouseReleased(release);
857 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
860 TEST_F(TextfieldTest, DragToSelect) {
861 InitTextfield();
862 textfield_->SetText(ASCIIToUTF16("hello world"));
863 const int kStart = GetCursorPositionX(5);
864 const int kEnd = 500;
865 gfx::Point start_point(kStart, 0);
866 gfx::Point end_point(kEnd, 0);
867 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, start_point, start_point,
868 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
869 ui::MouseEvent click_b(ui::ET_MOUSE_PRESSED, end_point, end_point,
870 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
871 ui::MouseEvent drag_left(ui::ET_MOUSE_DRAGGED, gfx::Point(), gfx::Point(),
872 ui::EF_LEFT_MOUSE_BUTTON, 0);
873 ui::MouseEvent drag_right(ui::ET_MOUSE_DRAGGED, end_point, end_point,
874 ui::EF_LEFT_MOUSE_BUTTON, 0);
875 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, end_point, end_point,
876 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
877 textfield_->OnMousePressed(click_a);
878 EXPECT_TRUE(textfield_->GetSelectedText().empty());
879 // Check that dragging left selects the beginning of the string.
880 textfield_->OnMouseDragged(drag_left);
881 base::string16 text_left = textfield_->GetSelectedText();
882 EXPECT_STR_EQ("hello", text_left);
883 // Check that dragging right selects the rest of the string.
884 textfield_->OnMouseDragged(drag_right);
885 base::string16 text_right = textfield_->GetSelectedText();
886 EXPECT_STR_EQ(" world", text_right);
887 // Check that releasing in the same location does not alter the selection.
888 textfield_->OnMouseReleased(release);
889 EXPECT_EQ(text_right, textfield_->GetSelectedText());
890 // Check that dragging from beyond the text length works too.
891 textfield_->OnMousePressed(click_b);
892 textfield_->OnMouseDragged(drag_left);
893 textfield_->OnMouseReleased(release);
894 EXPECT_EQ(textfield_->text(), textfield_->GetSelectedText());
897 #if defined(OS_WIN)
898 TEST_F(TextfieldTest, DragAndDrop_AcceptDrop) {
899 InitTextfield();
900 textfield_->SetText(ASCIIToUTF16("hello world"));
902 ui::OSExchangeData data;
903 base::string16 string(ASCIIToUTF16("string "));
904 data.SetString(string);
905 int formats = 0;
906 std::set<OSExchangeData::CustomFormat> custom_formats;
908 // Ensure that disabled textfields do not accept drops.
909 textfield_->SetEnabled(false);
910 EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
911 EXPECT_EQ(0, formats);
912 EXPECT_TRUE(custom_formats.empty());
913 EXPECT_FALSE(textfield_->CanDrop(data));
914 textfield_->SetEnabled(true);
916 // Ensure that read-only textfields do not accept drops.
917 textfield_->SetReadOnly(true);
918 EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
919 EXPECT_EQ(0, formats);
920 EXPECT_TRUE(custom_formats.empty());
921 EXPECT_FALSE(textfield_->CanDrop(data));
922 textfield_->SetReadOnly(false);
924 // Ensure that enabled and editable textfields do accept drops.
925 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
926 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
927 EXPECT_TRUE(custom_formats.empty());
928 EXPECT_TRUE(textfield_->CanDrop(data));
929 gfx::Point drop_point(GetCursorPositionX(6), 0);
930 ui::DropTargetEvent drop(data, drop_point, drop_point,
931 ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE);
932 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE,
933 textfield_->OnDragUpdated(drop));
934 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, textfield_->OnPerformDrop(drop));
935 EXPECT_STR_EQ("hello string world", textfield_->text());
937 // Ensure that textfields do not accept non-OSExchangeData::STRING types.
938 ui::OSExchangeData bad_data;
939 bad_data.SetFilename(base::FilePath(FILE_PATH_LITERAL("x")));
940 ui::OSExchangeData::CustomFormat fmt = ui::Clipboard::GetBitmapFormatType();
941 bad_data.SetPickledData(fmt, Pickle());
942 bad_data.SetFileContents(base::FilePath(L"x"), "x");
943 bad_data.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org"));
944 ui::OSExchangeData::DownloadFileInfo download(base::FilePath(), NULL);
945 bad_data.SetDownloadFileInfo(download);
946 EXPECT_FALSE(textfield_->CanDrop(bad_data));
948 #endif
950 TEST_F(TextfieldTest, DragAndDrop_InitiateDrag) {
951 InitTextfield();
952 textfield_->SetText(ASCIIToUTF16("hello string world"));
954 // Ensure the textfield will provide selected text for drag data.
955 base::string16 string;
956 ui::OSExchangeData data;
957 const gfx::Range kStringRange(6, 12);
958 textfield_->SelectRange(kStringRange);
959 const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
960 textfield_->WriteDragDataForView(NULL, kStringPoint, &data);
961 EXPECT_TRUE(data.GetString(&string));
962 EXPECT_EQ(textfield_->GetSelectedText(), string);
964 // Ensure that disabled textfields do not support drag operations.
965 textfield_->SetEnabled(false);
966 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
967 textfield_->GetDragOperationsForView(NULL, kStringPoint));
968 textfield_->SetEnabled(true);
969 // Ensure that textfields without selections do not support drag operations.
970 textfield_->ClearSelection();
971 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
972 textfield_->GetDragOperationsForView(NULL, kStringPoint));
973 textfield_->SelectRange(kStringRange);
974 // Ensure that password textfields do not support drag operations.
975 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
976 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
977 textfield_->GetDragOperationsForView(NULL, kStringPoint));
978 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
979 // Ensure that textfields only initiate drag operations inside the selection.
980 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, kStringPoint, kStringPoint,
981 ui::EF_LEFT_MOUSE_BUTTON,
982 ui::EF_LEFT_MOUSE_BUTTON);
983 textfield_->OnMousePressed(press_event);
984 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
985 textfield_->GetDragOperationsForView(NULL, gfx::Point()));
986 EXPECT_FALSE(textfield_->CanStartDragForView(NULL, gfx::Point(),
987 gfx::Point()));
988 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY,
989 textfield_->GetDragOperationsForView(NULL, kStringPoint));
990 EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
991 gfx::Point()));
992 // Ensure that textfields support local moves.
993 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
994 textfield_->GetDragOperationsForView(textfield_, kStringPoint));
997 TEST_F(TextfieldTest, DragAndDrop_ToTheRight) {
998 InitTextfield();
999 textfield_->SetText(ASCIIToUTF16("hello world"));
1001 base::string16 string;
1002 ui::OSExchangeData data;
1003 int formats = 0;
1004 int operations = 0;
1005 std::set<OSExchangeData::CustomFormat> custom_formats;
1007 // Start dragging "ello".
1008 textfield_->SelectRange(gfx::Range(1, 5));
1009 gfx::Point point(GetCursorPositionX(3), 0);
1010 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
1011 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1012 textfield_->OnMousePressed(click_a);
1013 EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
1014 gfx::Point()));
1015 operations = textfield_->GetDragOperationsForView(textfield_,
1016 click_a.location());
1017 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
1018 operations);
1019 textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
1020 EXPECT_TRUE(data.GetString(&string));
1021 EXPECT_EQ(textfield_->GetSelectedText(), string);
1022 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
1023 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
1024 EXPECT_TRUE(custom_formats.empty());
1026 // Drop "ello" after "w".
1027 const gfx::Point kDropPoint(GetCursorPositionX(7), 0);
1028 EXPECT_TRUE(textfield_->CanDrop(data));
1029 ui::DropTargetEvent drop_a(data, kDropPoint, kDropPoint, operations);
1030 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
1031 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
1032 EXPECT_STR_EQ("h welloorld", textfield_->text());
1033 textfield_->OnDragDone();
1035 // Undo/Redo the drag&drop change.
1036 SendKeyEvent(ui::VKEY_Z, false, true);
1037 EXPECT_STR_EQ("hello world", textfield_->text());
1038 SendKeyEvent(ui::VKEY_Z, false, true);
1039 EXPECT_STR_EQ("", textfield_->text());
1040 SendKeyEvent(ui::VKEY_Z, false, true);
1041 EXPECT_STR_EQ("", textfield_->text());
1042 SendKeyEvent(ui::VKEY_Y, false, true);
1043 EXPECT_STR_EQ("hello world", textfield_->text());
1044 SendKeyEvent(ui::VKEY_Y, false, true);
1045 EXPECT_STR_EQ("h welloorld", textfield_->text());
1046 SendKeyEvent(ui::VKEY_Y, false, true);
1047 EXPECT_STR_EQ("h welloorld", textfield_->text());
1050 TEST_F(TextfieldTest, DragAndDrop_ToTheLeft) {
1051 InitTextfield();
1052 textfield_->SetText(ASCIIToUTF16("hello world"));
1054 base::string16 string;
1055 ui::OSExchangeData data;
1056 int formats = 0;
1057 int operations = 0;
1058 std::set<OSExchangeData::CustomFormat> custom_formats;
1060 // Start dragging " worl".
1061 textfield_->SelectRange(gfx::Range(5, 10));
1062 gfx::Point point(GetCursorPositionX(7), 0);
1063 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
1064 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1065 textfield_->OnMousePressed(click_a);
1066 EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
1067 gfx::Point()));
1068 operations = textfield_->GetDragOperationsForView(textfield_,
1069 click_a.location());
1070 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
1071 operations);
1072 textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
1073 EXPECT_TRUE(data.GetString(&string));
1074 EXPECT_EQ(textfield_->GetSelectedText(), string);
1075 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
1076 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
1077 EXPECT_TRUE(custom_formats.empty());
1079 // Drop " worl" after "h".
1080 EXPECT_TRUE(textfield_->CanDrop(data));
1081 gfx::Point drop_point(GetCursorPositionX(1), 0);
1082 ui::DropTargetEvent drop_a(data, drop_point, drop_point, operations);
1083 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
1084 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
1085 EXPECT_STR_EQ("h worlellod", textfield_->text());
1086 textfield_->OnDragDone();
1088 // Undo/Redo the drag&drop change.
1089 SendKeyEvent(ui::VKEY_Z, false, true);
1090 EXPECT_STR_EQ("hello world", textfield_->text());
1091 SendKeyEvent(ui::VKEY_Z, false, true);
1092 EXPECT_STR_EQ("", textfield_->text());
1093 SendKeyEvent(ui::VKEY_Z, false, true);
1094 EXPECT_STR_EQ("", textfield_->text());
1095 SendKeyEvent(ui::VKEY_Y, false, true);
1096 EXPECT_STR_EQ("hello world", textfield_->text());
1097 SendKeyEvent(ui::VKEY_Y, false, true);
1098 EXPECT_STR_EQ("h worlellod", textfield_->text());
1099 SendKeyEvent(ui::VKEY_Y, false, true);
1100 EXPECT_STR_EQ("h worlellod", textfield_->text());
1103 TEST_F(TextfieldTest, DragAndDrop_Canceled) {
1104 InitTextfield();
1105 textfield_->SetText(ASCIIToUTF16("hello world"));
1107 // Start dragging "worl".
1108 textfield_->SelectRange(gfx::Range(6, 10));
1109 gfx::Point point(GetCursorPositionX(8), 0);
1110 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
1111 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1112 textfield_->OnMousePressed(click);
1113 ui::OSExchangeData data;
1114 textfield_->WriteDragDataForView(NULL, click.location(), &data);
1115 EXPECT_TRUE(textfield_->CanDrop(data));
1116 // Drag the text over somewhere valid, outside the current selection.
1117 gfx::Point drop_point(GetCursorPositionX(2), 0);
1118 ui::DropTargetEvent drop(data, drop_point, drop_point,
1119 ui::DragDropTypes::DRAG_MOVE);
1120 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop));
1121 // "Cancel" the drag, via move and release over the selection, and OnDragDone.
1122 gfx::Point drag_point(GetCursorPositionX(9), 0);
1123 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, drag_point, drag_point,
1124 ui::EF_LEFT_MOUSE_BUTTON, 0);
1125 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, drag_point, drag_point,
1126 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1127 textfield_->OnMouseDragged(drag);
1128 textfield_->OnMouseReleased(release);
1129 textfield_->OnDragDone();
1130 EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_->text());
1133 TEST_F(TextfieldTest, ReadOnlyTest) {
1134 InitTextfield();
1135 textfield_->SetText(ASCIIToUTF16("read only"));
1136 textfield_->SetReadOnly(true);
1137 EXPECT_TRUE(textfield_->enabled());
1138 EXPECT_TRUE(textfield_->IsFocusable());
1140 SendKeyEvent(ui::VKEY_HOME);
1141 EXPECT_EQ(0U, textfield_->GetCursorPosition());
1142 SendKeyEvent(ui::VKEY_END);
1143 EXPECT_EQ(9U, textfield_->GetCursorPosition());
1145 SendKeyEvent(ui::VKEY_LEFT, false, false);
1146 EXPECT_EQ(8U, textfield_->GetCursorPosition());
1147 SendKeyEvent(ui::VKEY_LEFT, false, true);
1148 EXPECT_EQ(5U, textfield_->GetCursorPosition());
1149 SendKeyEvent(ui::VKEY_LEFT, true, true);
1150 EXPECT_EQ(0U, textfield_->GetCursorPosition());
1151 EXPECT_STR_EQ("read ", textfield_->GetSelectedText());
1152 textfield_->SelectAll(false);
1153 EXPECT_STR_EQ("read only", textfield_->GetSelectedText());
1155 // Cut should be disabled.
1156 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1157 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
1158 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
1159 SendKeyEvent(ui::VKEY_X, false, true);
1160 SendKeyEvent(ui::VKEY_DELETE, true, false);
1161 EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1162 EXPECT_STR_EQ("read only", textfield_->text());
1164 // Paste should be disabled.
1165 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
1166 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
1167 SendKeyEvent(ui::VKEY_V, false, true);
1168 SendKeyEvent(ui::VKEY_INSERT, true, false);
1169 EXPECT_STR_EQ("read only", textfield_->text());
1171 // Copy should work normally.
1172 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1173 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
1174 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
1175 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1176 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1177 SendKeyEvent(ui::VKEY_C, false, true);
1178 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1179 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1180 SendKeyEvent(ui::VKEY_INSERT, false, true);
1181 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1183 // SetText should work even in read only mode.
1184 textfield_->SetText(ASCIIToUTF16(" four five six "));
1185 EXPECT_STR_EQ(" four five six ", textfield_->text());
1187 textfield_->SelectAll(false);
1188 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1190 // Text field is unmodifiable and selection shouldn't change.
1191 SendKeyEvent(ui::VKEY_DELETE);
1192 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1193 SendKeyEvent(ui::VKEY_BACK);
1194 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1195 SendKeyEvent(ui::VKEY_T);
1196 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1199 TEST_F(TextfieldTest, TextInputClientTest) {
1200 InitTextfield();
1201 ui::TextInputClient* client = textfield_->GetTextInputClient();
1202 EXPECT_TRUE(client);
1203 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, client->GetTextInputType());
1205 textfield_->SetText(ASCIIToUTF16("0123456789"));
1206 gfx::Range range;
1207 EXPECT_TRUE(client->GetTextRange(&range));
1208 EXPECT_EQ(0U, range.start());
1209 EXPECT_EQ(10U, range.end());
1211 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(1, 4)));
1212 EXPECT_TRUE(client->GetSelectionRange(&range));
1213 EXPECT_EQ(gfx::Range(1, 4), range);
1215 base::string16 substring;
1216 EXPECT_TRUE(client->GetTextFromRange(range, &substring));
1217 EXPECT_STR_EQ("123", substring);
1219 EXPECT_TRUE(client->DeleteRange(range));
1220 EXPECT_STR_EQ("0456789", textfield_->text());
1222 ui::CompositionText composition;
1223 composition.text = UTF8ToUTF16("321");
1224 // Set composition through input method.
1225 input_method_->Clear();
1226 input_method_->SetCompositionTextForNextKey(composition);
1227 textfield_->clear();
1229 on_before_user_action_ = on_after_user_action_ = 0;
1230 SendKeyEvent(ui::VKEY_A);
1231 EXPECT_TRUE(textfield_->key_received());
1232 EXPECT_FALSE(textfield_->key_handled());
1233 EXPECT_TRUE(client->HasCompositionText());
1234 EXPECT_TRUE(client->GetCompositionTextRange(&range));
1235 EXPECT_STR_EQ("0321456789", textfield_->text());
1236 EXPECT_EQ(gfx::Range(1, 4), range);
1237 EXPECT_EQ(1, on_before_user_action_);
1238 EXPECT_EQ(1, on_after_user_action_);
1240 input_method_->SetResultTextForNextKey(UTF8ToUTF16("123"));
1241 on_before_user_action_ = on_after_user_action_ = 0;
1242 textfield_->clear();
1243 SendKeyEvent(ui::VKEY_A);
1244 EXPECT_TRUE(textfield_->key_received());
1245 EXPECT_FALSE(textfield_->key_handled());
1246 EXPECT_FALSE(client->HasCompositionText());
1247 EXPECT_FALSE(input_method_->cancel_composition_called());
1248 EXPECT_STR_EQ("0123456789", textfield_->text());
1249 EXPECT_EQ(1, on_before_user_action_);
1250 EXPECT_EQ(1, on_after_user_action_);
1252 input_method_->Clear();
1253 input_method_->SetCompositionTextForNextKey(composition);
1254 textfield_->clear();
1255 SendKeyEvent(ui::VKEY_A);
1256 EXPECT_TRUE(client->HasCompositionText());
1257 EXPECT_STR_EQ("0123321456789", textfield_->text());
1259 on_before_user_action_ = on_after_user_action_ = 0;
1260 textfield_->clear();
1261 SendKeyEvent(ui::VKEY_RIGHT);
1262 EXPECT_FALSE(client->HasCompositionText());
1263 EXPECT_TRUE(input_method_->cancel_composition_called());
1264 EXPECT_TRUE(textfield_->key_received());
1265 EXPECT_TRUE(textfield_->key_handled());
1266 EXPECT_STR_EQ("0123321456789", textfield_->text());
1267 EXPECT_EQ(8U, textfield_->GetCursorPosition());
1268 EXPECT_EQ(1, on_before_user_action_);
1269 EXPECT_EQ(1, on_after_user_action_);
1271 textfield_->clear();
1272 textfield_->SetText(ASCIIToUTF16("0123456789"));
1273 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(5, 5)));
1274 client->ExtendSelectionAndDelete(4, 2);
1275 EXPECT_STR_EQ("0789", textfield_->text());
1277 // On{Before,After}UserAction should be called by whatever user action
1278 // triggers clearing or setting a selection if appropriate.
1279 on_before_user_action_ = on_after_user_action_ = 0;
1280 textfield_->clear();
1281 textfield_->ClearSelection();
1282 textfield_->SelectAll(false);
1283 EXPECT_EQ(0, on_before_user_action_);
1284 EXPECT_EQ(0, on_after_user_action_);
1286 input_method_->Clear();
1287 textfield_->SetReadOnly(true);
1288 EXPECT_TRUE(input_method_->text_input_type_changed());
1289 EXPECT_FALSE(textfield_->GetTextInputClient());
1291 textfield_->SetReadOnly(false);
1292 input_method_->Clear();
1293 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
1294 EXPECT_TRUE(input_method_->text_input_type_changed());
1295 EXPECT_TRUE(textfield_->GetTextInputClient());
1298 TEST_F(TextfieldTest, UndoRedoTest) {
1299 InitTextfield();
1300 SendKeyEvent(ui::VKEY_A);
1301 EXPECT_STR_EQ("a", textfield_->text());
1302 SendKeyEvent(ui::VKEY_Z, false, true);
1303 EXPECT_STR_EQ("", textfield_->text());
1304 SendKeyEvent(ui::VKEY_Z, false, true);
1305 EXPECT_STR_EQ("", textfield_->text());
1306 SendKeyEvent(ui::VKEY_Y, false, true);
1307 EXPECT_STR_EQ("a", textfield_->text());
1308 SendKeyEvent(ui::VKEY_Y, false, true);
1309 EXPECT_STR_EQ("a", textfield_->text());
1311 // AppendText
1312 textfield_->AppendText(ASCIIToUTF16("b"));
1313 last_contents_.clear(); // AppendText doesn't call ContentsChanged.
1314 EXPECT_STR_EQ("ab", textfield_->text());
1315 SendKeyEvent(ui::VKEY_Z, false, true);
1316 EXPECT_STR_EQ("a", textfield_->text());
1317 SendKeyEvent(ui::VKEY_Y, false, true);
1318 EXPECT_STR_EQ("ab", textfield_->text());
1320 // SetText
1321 SendKeyEvent(ui::VKEY_C);
1322 // Undo'ing append moves the cursor to the end for now.
1323 // A no-op SetText won't add a new edit; see TextfieldModel::SetText.
1324 EXPECT_STR_EQ("abc", textfield_->text());
1325 textfield_->SetText(ASCIIToUTF16("abc"));
1326 EXPECT_STR_EQ("abc", textfield_->text());
1327 SendKeyEvent(ui::VKEY_Z, false, true);
1328 EXPECT_STR_EQ("ab", textfield_->text());
1329 SendKeyEvent(ui::VKEY_Y, false, true);
1330 EXPECT_STR_EQ("abc", textfield_->text());
1331 SendKeyEvent(ui::VKEY_Y, false, true);
1332 EXPECT_STR_EQ("abc", textfield_->text());
1333 textfield_->SetText(ASCIIToUTF16("123"));
1334 textfield_->SetText(ASCIIToUTF16("123"));
1335 EXPECT_STR_EQ("123", textfield_->text());
1336 SendKeyEvent(ui::VKEY_END, false, false);
1337 SendKeyEvent(ui::VKEY_4, false, false);
1338 EXPECT_STR_EQ("1234", textfield_->text());
1339 last_contents_.clear();
1340 SendKeyEvent(ui::VKEY_Z, false, true);
1341 EXPECT_STR_EQ("123", textfield_->text());
1342 SendKeyEvent(ui::VKEY_Z, false, true);
1343 // the insert edit "c" and set edit "123" are merged to single edit,
1344 // so text becomes "ab" after undo.
1345 EXPECT_STR_EQ("ab", textfield_->text());
1346 SendKeyEvent(ui::VKEY_Z, false, true);
1347 EXPECT_STR_EQ("a", textfield_->text());
1348 SendKeyEvent(ui::VKEY_Y, false, true);
1349 EXPECT_STR_EQ("ab", textfield_->text());
1350 SendKeyEvent(ui::VKEY_Y, false, true);
1351 EXPECT_STR_EQ("123", textfield_->text());
1352 SendKeyEvent(ui::VKEY_Y, false, true);
1353 EXPECT_STR_EQ("1234", textfield_->text());
1355 // Undoing to the same text shouldn't call ContentsChanged.
1356 SendKeyEvent(ui::VKEY_A, false, true); // select all
1357 SendKeyEvent(ui::VKEY_A);
1358 EXPECT_STR_EQ("a", textfield_->text());
1359 SendKeyEvent(ui::VKEY_B);
1360 SendKeyEvent(ui::VKEY_C);
1361 EXPECT_STR_EQ("abc", textfield_->text());
1362 SendKeyEvent(ui::VKEY_Z, false, true);
1363 EXPECT_STR_EQ("1234", textfield_->text());
1364 SendKeyEvent(ui::VKEY_Y, false, true);
1365 EXPECT_STR_EQ("abc", textfield_->text());
1367 // Delete/Backspace
1368 SendKeyEvent(ui::VKEY_BACK);
1369 EXPECT_STR_EQ("ab", textfield_->text());
1370 SendKeyEvent(ui::VKEY_HOME);
1371 SendKeyEvent(ui::VKEY_DELETE);
1372 EXPECT_STR_EQ("b", textfield_->text());
1373 SendKeyEvent(ui::VKEY_A, false, true);
1374 SendKeyEvent(ui::VKEY_DELETE);
1375 EXPECT_STR_EQ("", textfield_->text());
1376 SendKeyEvent(ui::VKEY_Z, false, true);
1377 EXPECT_STR_EQ("b", textfield_->text());
1378 SendKeyEvent(ui::VKEY_Z, false, true);
1379 EXPECT_STR_EQ("ab", textfield_->text());
1380 SendKeyEvent(ui::VKEY_Z, false, true);
1381 EXPECT_STR_EQ("abc", textfield_->text());
1382 SendKeyEvent(ui::VKEY_Y, false, true);
1383 EXPECT_STR_EQ("ab", textfield_->text());
1384 SendKeyEvent(ui::VKEY_Y, false, true);
1385 EXPECT_STR_EQ("b", textfield_->text());
1386 SendKeyEvent(ui::VKEY_Y, false, true);
1387 EXPECT_STR_EQ("", textfield_->text());
1388 SendKeyEvent(ui::VKEY_Y, false, true);
1389 EXPECT_STR_EQ("", textfield_->text());
1392 TEST_F(TextfieldTest, CutCopyPaste) {
1393 InitTextfield();
1395 // Ensure IDS_APP_CUT cuts.
1396 textfield_->SetText(ASCIIToUTF16("123"));
1397 textfield_->SelectAll(false);
1398 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
1399 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
1400 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1401 EXPECT_STR_EQ("", textfield_->text());
1402 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1404 // Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
1405 textfield_->SetText(ASCIIToUTF16("456"));
1406 textfield_->SelectAll(false);
1407 SendKeyEvent(ui::VKEY_X, true, false, true, false);
1408 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1409 EXPECT_STR_EQ("456", textfield_->text());
1410 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1411 SendKeyEvent(ui::VKEY_X, false, true);
1412 EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1413 EXPECT_STR_EQ("", textfield_->text());
1414 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
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", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1421 EXPECT_STR_EQ("", textfield_->text());
1422 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1424 // Ensure IDS_APP_COPY copies.
1425 textfield_->SetText(ASCIIToUTF16("789"));
1426 textfield_->SelectAll(false);
1427 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
1428 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
1429 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1430 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1432 // Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
1433 textfield_->SetText(ASCIIToUTF16("012"));
1434 textfield_->SelectAll(false);
1435 SendKeyEvent(ui::VKEY_C, true, false, true, false);
1436 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1437 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1438 SendKeyEvent(ui::VKEY_C, false, true);
1439 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1440 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1442 // Ensure [Ctrl]+[Insert] copies.
1443 textfield_->SetText(ASCIIToUTF16("345"));
1444 textfield_->SelectAll(false);
1445 SendKeyEvent(ui::VKEY_INSERT, false, true);
1446 EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1447 EXPECT_STR_EQ("345", textfield_->text());
1448 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1450 // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
1451 // also ensure that [Ctrl]+[Alt]+[V] does nothing.
1452 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "abc");
1453 textfield_->SetText(base::string16());
1454 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
1455 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
1456 EXPECT_STR_EQ("abc", textfield_->text());
1457 SendKeyEvent(ui::VKEY_V, false, true);
1458 EXPECT_STR_EQ("abcabc", textfield_->text());
1459 SendKeyEvent(ui::VKEY_INSERT, true, false);
1460 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1461 SendKeyEvent(ui::VKEY_V, true, false, true, false);
1462 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1464 // Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
1465 textfield_->SelectAll(false);
1466 SendKeyEvent(ui::VKEY_INSERT, true, true);
1467 EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1468 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1469 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1472 TEST_F(TextfieldTest, OvertypeMode) {
1473 InitTextfield();
1474 // Overtype mode should be disabled (no-op [Insert]).
1475 textfield_->SetText(ASCIIToUTF16("2"));
1476 SendKeyEvent(ui::VKEY_HOME);
1477 SendKeyEvent(ui::VKEY_INSERT);
1478 SendKeyEvent(ui::VKEY_1, false, false);
1479 EXPECT_STR_EQ("12", textfield_->text());
1482 TEST_F(TextfieldTest, TextCursorDisplayTest) {
1483 InitTextfield();
1484 // LTR-RTL string in LTR context.
1485 SendKeyEvent('a');
1486 EXPECT_STR_EQ("a", textfield_->text());
1487 int x = GetCursorBounds().x();
1488 int prev_x = x;
1490 SendKeyEvent('b');
1491 EXPECT_STR_EQ("ab", textfield_->text());
1492 x = GetCursorBounds().x();
1493 EXPECT_LT(prev_x, x);
1494 prev_x = x;
1496 SendKeyEvent(0x05E1);
1497 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text());
1498 x = GetCursorBounds().x();
1499 EXPECT_GE(1, std::abs(x - prev_x));
1501 SendKeyEvent(0x05E2);
1502 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text());
1503 x = GetCursorBounds().x();
1504 EXPECT_GE(1, std::abs(x - prev_x));
1506 // Clear text.
1507 SendKeyEvent(ui::VKEY_A, false, true);
1508 SendKeyEvent(ui::VKEY_DELETE);
1510 // RTL-LTR string in LTR context.
1511 SendKeyEvent(0x05E1);
1512 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text());
1513 x = GetCursorBounds().x();
1514 EXPECT_EQ(GetDisplayRect().x(), x);
1515 prev_x = x;
1517 SendKeyEvent(0x05E2);
1518 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text());
1519 x = GetCursorBounds().x();
1520 EXPECT_GE(1, std::abs(x - prev_x));
1522 SendKeyEvent('a');
1523 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text());
1524 x = GetCursorBounds().x();
1525 EXPECT_LT(prev_x, x);
1526 prev_x = x;
1528 SendKeyEvent('b');
1529 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text());
1530 x = GetCursorBounds().x();
1531 EXPECT_LT(prev_x, x);
1534 TEST_F(TextfieldTest, TextCursorDisplayInRTLTest) {
1535 std::string locale = l10n_util::GetApplicationLocale("");
1536 base::i18n::SetICUDefaultLocale("he");
1538 InitTextfield();
1539 // LTR-RTL string in RTL context.
1540 SendKeyEvent('a');
1541 EXPECT_STR_EQ("a", textfield_->text());
1542 int x = GetCursorBounds().x();
1543 EXPECT_EQ(GetDisplayRect().right() - 1, x);
1544 int prev_x = x;
1546 SendKeyEvent('b');
1547 EXPECT_STR_EQ("ab", textfield_->text());
1548 x = GetCursorBounds().x();
1549 EXPECT_GE(1, std::abs(x - prev_x));
1551 SendKeyEvent(0x05E1);
1552 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text());
1553 x = GetCursorBounds().x();
1554 EXPECT_GT(prev_x, x);
1555 prev_x = x;
1557 SendKeyEvent(0x05E2);
1558 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text());
1559 x = GetCursorBounds().x();
1560 EXPECT_GT(prev_x, x);
1562 // Clear text.
1563 SendKeyEvent(ui::VKEY_A, false, true);
1564 SendKeyEvent(ui::VKEY_DELETE);
1566 // RTL-LTR string in RTL context.
1567 SendKeyEvent(0x05E1);
1568 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text());
1569 x = GetCursorBounds().x();
1570 prev_x = x;
1572 SendKeyEvent(0x05E2);
1573 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text());
1574 x = GetCursorBounds().x();
1575 EXPECT_GT(prev_x, x);
1576 prev_x = x;
1578 SendKeyEvent('a');
1579 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text());
1580 x = GetCursorBounds().x();
1581 EXPECT_GE(1, std::abs(x - prev_x));
1582 prev_x = x;
1584 SendKeyEvent('b');
1585 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text());
1586 x = GetCursorBounds().x();
1587 EXPECT_EQ(prev_x, x);
1589 // Reset locale.
1590 base::i18n::SetICUDefaultLocale(locale);
1593 TEST_F(TextfieldTest, HitInsideTextAreaTest) {
1594 InitTextfield();
1595 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
1596 std::vector<gfx::Rect> cursor_bounds;
1598 // Save each cursor bound.
1599 gfx::SelectionModel sel(0, gfx::CURSOR_FORWARD);
1600 cursor_bounds.push_back(GetCursorBounds(sel));
1602 sel = gfx::SelectionModel(1, gfx::CURSOR_BACKWARD);
1603 gfx::Rect bound = GetCursorBounds(sel);
1604 sel = gfx::SelectionModel(1, gfx::CURSOR_FORWARD);
1605 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1606 cursor_bounds.push_back(bound);
1608 // Check that a cursor at the end of the Latin portion of the text is at the
1609 // same position as a cursor placed at the end of the RTL Hebrew portion.
1610 sel = gfx::SelectionModel(2, gfx::CURSOR_BACKWARD);
1611 bound = GetCursorBounds(sel);
1612 sel = gfx::SelectionModel(4, gfx::CURSOR_BACKWARD);
1613 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1614 cursor_bounds.push_back(bound);
1616 sel = gfx::SelectionModel(3, gfx::CURSOR_BACKWARD);
1617 bound = GetCursorBounds(sel);
1618 sel = gfx::SelectionModel(3, gfx::CURSOR_FORWARD);
1619 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1620 cursor_bounds.push_back(bound);
1622 sel = gfx::SelectionModel(2, gfx::CURSOR_FORWARD);
1623 bound = GetCursorBounds(sel);
1624 sel = gfx::SelectionModel(4, gfx::CURSOR_FORWARD);
1625 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1626 cursor_bounds.push_back(bound);
1628 // Expected cursor position when clicking left and right of each character.
1629 size_t cursor_pos_expected[] = {0, 1, 1, 2, 4, 3, 3, 2};
1631 int index = 0;
1632 for (int i = 0; i < static_cast<int>(cursor_bounds.size() - 1); ++i) {
1633 int half_width = (cursor_bounds[i + 1].x() - cursor_bounds[i].x()) / 2;
1634 MouseClick(cursor_bounds[i], half_width / 2);
1635 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition());
1637 // To avoid trigger double click. Not using sleep() since it takes longer
1638 // for the test to run if using sleep().
1639 NonClientMouseClick();
1641 MouseClick(cursor_bounds[i + 1], - (half_width / 2));
1642 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition());
1644 NonClientMouseClick();
1648 TEST_F(TextfieldTest, HitOutsideTextAreaTest) {
1649 InitTextfield();
1651 // LTR-RTL string in LTR context.
1652 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
1654 SendKeyEvent(ui::VKEY_HOME);
1655 gfx::Rect bound = GetCursorBounds();
1656 MouseClick(bound, -10);
1657 EXPECT_EQ(bound, GetCursorBounds());
1659 SendKeyEvent(ui::VKEY_END);
1660 bound = GetCursorBounds();
1661 MouseClick(bound, 10);
1662 EXPECT_EQ(bound, GetCursorBounds());
1664 NonClientMouseClick();
1666 // RTL-LTR string in LTR context.
1667 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab"));
1669 SendKeyEvent(ui::VKEY_HOME);
1670 bound = GetCursorBounds();
1671 MouseClick(bound, 10);
1672 EXPECT_EQ(bound, GetCursorBounds());
1674 SendKeyEvent(ui::VKEY_END);
1675 bound = GetCursorBounds();
1676 MouseClick(bound, -10);
1677 EXPECT_EQ(bound, GetCursorBounds());
1680 TEST_F(TextfieldTest, HitOutsideTextAreaInRTLTest) {
1681 std::string locale = l10n_util::GetApplicationLocale("");
1682 base::i18n::SetICUDefaultLocale("he");
1684 InitTextfield();
1686 // RTL-LTR string in RTL context.
1687 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab"));
1688 SendKeyEvent(ui::VKEY_HOME);
1689 gfx::Rect bound = GetCursorBounds();
1690 MouseClick(bound, 10);
1691 EXPECT_EQ(bound, GetCursorBounds());
1693 SendKeyEvent(ui::VKEY_END);
1694 bound = GetCursorBounds();
1695 MouseClick(bound, -10);
1696 EXPECT_EQ(bound, GetCursorBounds());
1698 NonClientMouseClick();
1700 // LTR-RTL string in RTL context.
1701 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
1702 SendKeyEvent(ui::VKEY_HOME);
1703 bound = GetCursorBounds();
1704 MouseClick(bound, -10);
1705 EXPECT_EQ(bound, GetCursorBounds());
1707 SendKeyEvent(ui::VKEY_END);
1708 bound = GetCursorBounds();
1709 MouseClick(bound, 10);
1710 EXPECT_EQ(bound, GetCursorBounds());
1712 // Reset locale.
1713 base::i18n::SetICUDefaultLocale(locale);
1716 TEST_F(TextfieldTest, OverflowTest) {
1717 InitTextfield();
1719 base::string16 str;
1720 for (int i = 0; i < 500; ++i)
1721 SendKeyEvent('a');
1722 SendKeyEvent(kHebrewLetterSamekh);
1723 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1725 // Test mouse pointing.
1726 MouseClick(GetCursorBounds(), -1);
1727 EXPECT_EQ(500U, textfield_->GetCursorPosition());
1729 // Clear text.
1730 SendKeyEvent(ui::VKEY_A, false, true);
1731 SendKeyEvent(ui::VKEY_DELETE);
1733 for (int i = 0; i < 500; ++i)
1734 SendKeyEvent(kHebrewLetterSamekh);
1735 SendKeyEvent('a');
1736 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1738 MouseClick(GetCursorBounds(), -1);
1739 EXPECT_EQ(501U, textfield_->GetCursorPosition());
1742 TEST_F(TextfieldTest, OverflowInRTLTest) {
1743 std::string locale = l10n_util::GetApplicationLocale("");
1744 base::i18n::SetICUDefaultLocale("he");
1746 InitTextfield();
1748 base::string16 str;
1749 for (int i = 0; i < 500; ++i)
1750 SendKeyEvent('a');
1751 SendKeyEvent(kHebrewLetterSamekh);
1752 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1754 MouseClick(GetCursorBounds(), 1);
1755 EXPECT_EQ(501U, textfield_->GetCursorPosition());
1757 // Clear text.
1758 SendKeyEvent(ui::VKEY_A, false, true);
1759 SendKeyEvent(ui::VKEY_DELETE);
1761 for (int i = 0; i < 500; ++i)
1762 SendKeyEvent(kHebrewLetterSamekh);
1763 SendKeyEvent('a');
1764 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1766 MouseClick(GetCursorBounds(), 1);
1767 EXPECT_EQ(500U, textfield_->GetCursorPosition());
1769 // Reset locale.
1770 base::i18n::SetICUDefaultLocale(locale);
1773 TEST_F(TextfieldTest, GetCompositionCharacterBoundsTest) {
1774 InitTextfield();
1775 ui::CompositionText composition;
1776 composition.text = UTF8ToUTF16("abc123");
1777 const uint32 char_count = static_cast<uint32>(composition.text.length());
1778 ui::TextInputClient* client = textfield_->GetTextInputClient();
1780 // Compare the composition character bounds with surrounding cursor bounds.
1781 for (uint32 i = 0; i < char_count; ++i) {
1782 composition.selection = gfx::Range(i);
1783 client->SetCompositionText(composition);
1784 gfx::Point cursor_origin = GetCursorBounds().origin();
1785 views::View::ConvertPointToScreen(textfield_, &cursor_origin);
1787 composition.selection = gfx::Range(i + 1);
1788 client->SetCompositionText(composition);
1789 gfx::Point next_cursor_bottom_left = GetCursorBounds().bottom_left();
1790 views::View::ConvertPointToScreen(textfield_, &next_cursor_bottom_left);
1792 gfx::Rect character;
1793 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &character));
1794 EXPECT_EQ(character.origin(), cursor_origin) << " i=" << i;
1795 EXPECT_EQ(character.bottom_right(), next_cursor_bottom_left) << " i=" << i;
1798 // Return false if the index is out of range.
1799 gfx::Rect rect;
1800 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count, &rect));
1801 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 1, &rect));
1802 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 100, &rect));
1805 TEST_F(TextfieldTest, GetCompositionCharacterBounds_ComplexText) {
1806 InitTextfield();
1808 const base::char16 kUtf16Chars[] = {
1809 // U+0020 SPACE
1810 0x0020,
1811 // U+1F408 (CAT) as surrogate pair
1812 0xd83d, 0xdc08,
1813 // U+5642 as Ideographic Variation Sequences
1814 0x5642, 0xDB40, 0xDD00,
1815 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences
1816 0x260E, 0xFE0F,
1817 // U+0020 SPACE
1818 0x0020,
1820 const size_t kUtf16CharsCount = arraysize(kUtf16Chars);
1822 ui::CompositionText composition;
1823 composition.text.assign(kUtf16Chars, kUtf16Chars + kUtf16CharsCount);
1824 ui::TextInputClient* client = textfield_->GetTextInputClient();
1825 client->SetCompositionText(composition);
1827 // Make sure GetCompositionCharacterBounds never fails for index.
1828 gfx::Rect rects[kUtf16CharsCount];
1829 gfx::Rect prev_cursor = GetCursorBounds();
1830 for (uint32 i = 0; i < kUtf16CharsCount; ++i)
1831 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &rects[i]));
1833 // Here we might expect the following results but it actually depends on how
1834 // Uniscribe or HarfBuzz treats them with given font.
1835 // - rects[1] == rects[2]
1836 // - rects[3] == rects[4] == rects[5]
1837 // - rects[6] == rects[7]
1840 // The word we select by double clicking should remain selected regardless of
1841 // where we drag the mouse afterwards without releasing the left button.
1842 TEST_F(TextfieldTest, KeepInitiallySelectedWord) {
1843 InitTextfield();
1845 textfield_->SetText(ASCIIToUTF16("abc def ghi"));
1847 textfield_->SelectRange(gfx::Range(5, 5));
1848 const gfx::Rect middle_cursor = GetCursorBounds();
1849 textfield_->SelectRange(gfx::Range(0, 0));
1850 const gfx::Point beginning = GetCursorBounds().origin();
1852 // Double click, but do not release the left button.
1853 MouseClick(middle_cursor, 0);
1854 const gfx::Point middle(middle_cursor.x(),
1855 middle_cursor.y() + middle_cursor.height() / 2);
1856 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, middle, middle,
1857 ui::EF_LEFT_MOUSE_BUTTON,
1858 ui::EF_LEFT_MOUSE_BUTTON);
1859 textfield_->OnMousePressed(press_event);
1860 EXPECT_EQ(gfx::Range(4, 7), textfield_->GetSelectedRange());
1862 // Drag the mouse to the beginning of the textfield.
1863 ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, beginning, beginning,
1864 ui::EF_LEFT_MOUSE_BUTTON, 0);
1865 textfield_->OnMouseDragged(drag_event);
1866 EXPECT_EQ(gfx::Range(7, 0), textfield_->GetSelectedRange());
1869 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1870 // flaky: http://crbug.com/396477
1871 TEST_F(TextfieldTest, DISABLED_SelectionClipboard) {
1872 InitTextfield();
1873 textfield_->SetText(ASCIIToUTF16("0123"));
1874 gfx::Point point_1(GetCursorPositionX(1), 0);
1875 gfx::Point point_2(GetCursorPositionX(2), 0);
1876 gfx::Point point_3(GetCursorPositionX(3), 0);
1877 gfx::Point point_4(GetCursorPositionX(4), 0);
1879 // Text selected by the mouse should be placed on the selection clipboard.
1880 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, point_1, point_1,
1881 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1882 textfield_->OnMousePressed(press);
1883 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, point_3, point_3,
1884 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1885 textfield_->OnMouseDragged(drag);
1886 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point_3, point_3,
1887 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1888 textfield_->OnMouseReleased(release);
1889 EXPECT_EQ(gfx::Range(1, 3), textfield_->GetSelectedRange());
1890 EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1892 // Select-all should update the selection clipboard.
1893 SendKeyEvent(ui::VKEY_A, false, true);
1894 EXPECT_EQ(gfx::Range(0, 4), textfield_->GetSelectedRange());
1895 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1896 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1898 // Shift-click selection modifications should update the clipboard.
1899 NonClientMouseClick();
1900 ui::MouseEvent press_2(ui::ET_MOUSE_PRESSED, point_2, point_2,
1901 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1902 press_2.set_flags(press_2.flags() | ui::EF_SHIFT_DOWN);
1903 #if defined(USE_X11)
1904 ui::UpdateX11EventForFlags(&press_2);
1905 #endif
1906 textfield_->OnMousePressed(press_2);
1907 ui::MouseEvent release_2(ui::ET_MOUSE_RELEASED, point_2, point_2,
1908 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1909 textfield_->OnMouseReleased(release_2);
1910 EXPECT_EQ(gfx::Range(0, 2), textfield_->GetSelectedRange());
1911 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1912 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1914 // Shift-Left/Right should update the selection clipboard.
1915 SendKeyEvent(ui::VKEY_RIGHT, true, false);
1916 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1917 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1918 SendKeyEvent(ui::VKEY_LEFT, true, false);
1919 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1920 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1921 SendKeyEvent(ui::VKEY_RIGHT, true, true);
1922 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1923 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1925 // Moving the cursor without a selection should not change the clipboard.
1926 SendKeyEvent(ui::VKEY_LEFT, false, false);
1927 EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
1928 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1929 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1931 // Middle clicking should paste at the mouse (not cursor) location.
1932 ui::MouseEvent middle(ui::ET_MOUSE_PRESSED, point_4, point_4,
1933 ui::EF_MIDDLE_MOUSE_BUTTON, ui::EF_MIDDLE_MOUSE_BUTTON);
1934 textfield_->OnMousePressed(middle);
1935 EXPECT_STR_EQ("01230123", textfield_->text());
1936 EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
1937 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1939 // Middle click pasting should adjust trailing cursors.
1940 textfield_->SelectRange(gfx::Range(5, 5));
1941 textfield_->OnMousePressed(middle);
1942 EXPECT_STR_EQ("012301230123", textfield_->text());
1943 EXPECT_EQ(gfx::Range(9, 9), textfield_->GetSelectedRange());
1945 // Middle click pasting should adjust trailing selections.
1946 textfield_->SelectRange(gfx::Range(7, 9));
1947 textfield_->OnMousePressed(middle);
1948 EXPECT_STR_EQ("0123012301230123", textfield_->text());
1949 EXPECT_EQ(gfx::Range(11, 13), textfield_->GetSelectedRange());
1951 // Middle clicking in the selection should clear the clipboard and selection.
1952 textfield_->SelectRange(gfx::Range(2, 6));
1953 textfield_->OnMousePressed(middle);
1954 EXPECT_STR_EQ("0123012301230123", textfield_->text());
1955 EXPECT_EQ(gfx::Range(6, 6), textfield_->GetSelectedRange());
1956 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
1958 // Double and triple clicking should update the clipboard contents.
1959 textfield_->SetText(ASCIIToUTF16("ab cd ef"));
1960 gfx::Point word(GetCursorPositionX(4), 0);
1961 ui::MouseEvent press_word(ui::ET_MOUSE_PRESSED, word, word,
1962 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1963 textfield_->OnMousePressed(press_word);
1964 ui::MouseEvent release_word(ui::ET_MOUSE_RELEASED, word, word,
1965 ui::EF_LEFT_MOUSE_BUTTON,
1966 ui::EF_LEFT_MOUSE_BUTTON);
1967 textfield_->OnMouseReleased(release_word);
1968 ui::MouseEvent double_click(ui::ET_MOUSE_PRESSED, word, word,
1969 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
1970 ui::EF_LEFT_MOUSE_BUTTON);
1971 textfield_->OnMousePressed(double_click);
1972 textfield_->OnMouseReleased(release_word);
1973 EXPECT_EQ(gfx::Range(3, 5), textfield_->GetSelectedRange());
1974 EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1975 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1976 textfield_->OnMousePressed(press_word);
1977 textfield_->OnMouseReleased(release_word);
1978 EXPECT_EQ(gfx::Range(0, 8), textfield_->GetSelectedRange());
1979 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1980 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1982 // Selecting a range of text without any user interaction should not change
1983 // the clipboard content.
1984 textfield_->SelectRange(gfx::Range(0, 3));
1985 EXPECT_STR_EQ("ab ", textfield_->GetSelectedText());
1986 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1987 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1989 SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION, "other");
1990 textfield_->SelectAll(false);
1991 EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1992 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1994 #endif
1996 // Long_Press gesture in Textfield can initiate a drag and drop now.
1997 TEST_F(TextfieldTest, TestLongPressInitiatesDragDrop) {
1998 InitTextfield();
1999 textfield_->SetText(ASCIIToUTF16("Hello string world"));
2001 // Ensure the textfield will provide selected text for drag data.
2002 textfield_->SelectRange(gfx::Range(6, 12));
2003 const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
2005 // Enable touch-drag-drop to make long press effective.
2006 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2007 switches::kEnableTouchDragDrop);
2009 // Create a long press event in the selected region should start a drag.
2010 GestureEventForTest long_press(
2011 kStringPoint.x(),
2012 kStringPoint.y(),
2013 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2014 textfield_->OnGestureEvent(&long_press);
2015 EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
2016 kStringPoint));
2019 TEST_F(TextfieldTest, GetTextfieldBaseline_FontFallbackTest) {
2020 InitTextfield();
2021 textfield_->SetText(UTF8ToUTF16("abc"));
2022 const int old_baseline = textfield_->GetBaseline();
2024 // Set text which may fall back to a font which has taller baseline than
2025 // the default font.
2026 textfield_->SetText(UTF8ToUTF16("\xE0\xB9\x91"));
2027 const int new_baseline = textfield_->GetBaseline();
2029 // Regardless of the text, the baseline must be the same.
2030 EXPECT_EQ(new_baseline, old_baseline);
2033 // Tests that a textfield view can be destroyed from OnKeyEvent() on its
2034 // controller and it does not crash.
2035 TEST_F(TextfieldTest, DestroyingTextfieldFromOnKeyEvent) {
2036 InitTextfield();
2038 // The controller assumes ownership of the textfield.
2039 TextfieldDestroyerController controller(textfield_);
2040 EXPECT_TRUE(controller.target());
2042 // Send a key to trigger OnKeyEvent().
2043 SendKeyEvent('X');
2045 EXPECT_FALSE(controller.target());
2048 class TextfieldTouchSelectionTest : public TextfieldTest {
2049 public:
2050 // TextfieldTest:
2051 void SetUp() override {
2052 TextfieldTest::SetUp();
2053 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2054 switches::kEnableTouchEditing);
2057 protected:
2058 // Simulates a complete tap.
2059 void Tap(const gfx::Point& point) {
2060 GestureEventForTest begin(
2061 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_BEGIN));
2062 textfield_->OnGestureEvent(&begin);
2064 GestureEventForTest tap_down(
2065 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
2066 textfield_->OnGestureEvent(&tap_down);
2068 GestureEventForTest show_press(
2069 point.x(),
2070 point.y(),
2071 ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS));
2072 textfield_->OnGestureEvent(&show_press);
2074 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
2075 tap_details.set_tap_count(1);
2076 GestureEventForTest tap(point.x(), point.y(), tap_details);
2077 textfield_->OnGestureEvent(&tap);
2079 GestureEventForTest end(
2080 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_END));
2081 textfield_->OnGestureEvent(&end);
2086 // Touch selection and dragging currently only works for chromeos.
2087 #if defined(OS_CHROMEOS)
2088 TEST_F(TextfieldTouchSelectionTest, TouchSelectionAndDraggingTest) {
2089 InitTextfield();
2090 textfield_->SetText(ASCIIToUTF16("hello world"));
2091 EXPECT_FALSE(test_api_->touch_selection_controller());
2092 const int x = GetCursorPositionX(2);
2094 // Tapping on the textfield should turn on the TouchSelectionController.
2095 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
2096 tap_details.set_tap_count(1);
2097 GestureEventForTest tap(x, 0, tap_details);
2098 textfield_->OnGestureEvent(&tap);
2099 EXPECT_TRUE(test_api_->touch_selection_controller());
2101 // Un-focusing the textfield should reset the TouchSelectionController
2102 textfield_->GetFocusManager()->ClearFocus();
2103 EXPECT_FALSE(test_api_->touch_selection_controller());
2104 textfield_->RequestFocus();
2106 // With touch editing enabled, long press should not show context menu.
2107 // Instead, select word and invoke TouchSelectionController.
2108 GestureEventForTest long_press_1(
2109 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2110 textfield_->OnGestureEvent(&long_press_1);
2111 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
2112 EXPECT_TRUE(test_api_->touch_selection_controller());
2113 EXPECT_TRUE(long_press_1.handled());
2115 // With touch drag drop enabled, long pressing in the selected region should
2116 // start a drag and remove TouchSelectionController.
2117 ASSERT_TRUE(switches::IsTouchDragDropEnabled());
2118 GestureEventForTest long_press_2(
2119 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2120 textfield_->OnGestureEvent(&long_press_2);
2121 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
2122 EXPECT_FALSE(test_api_->touch_selection_controller());
2123 EXPECT_FALSE(long_press_2.handled());
2125 // After disabling touch drag drop, long pressing again in the selection
2126 // region should not do anything.
2127 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2128 switches::kDisableTouchDragDrop);
2129 ASSERT_FALSE(switches::IsTouchDragDropEnabled());
2130 GestureEventForTest long_press_3(
2131 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2132 textfield_->OnGestureEvent(&long_press_3);
2133 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
2134 EXPECT_FALSE(test_api_->touch_selection_controller());
2135 EXPECT_FALSE(long_press_3.handled());
2137 #endif
2139 TEST_F(TextfieldTouchSelectionTest, TouchSelectionInUnfocusableTextfield) {
2140 InitTextfield();
2141 textfield_->SetText(ASCIIToUTF16("hello world"));
2142 gfx::Point touch_point(GetCursorPositionX(2), 0);
2144 // Disable textfield and tap on it. Touch text selection should not get
2145 // activated.
2146 textfield_->SetEnabled(false);
2147 Tap(touch_point);
2148 EXPECT_FALSE(test_api_->touch_selection_controller());
2149 textfield_->SetEnabled(true);
2151 // Make textfield unfocusable and tap on it. Touch text selection should not
2152 // get activated.
2153 textfield_->SetFocusable(false);
2154 Tap(touch_point);
2155 EXPECT_FALSE(textfield_->HasFocus());
2156 EXPECT_FALSE(test_api_->touch_selection_controller());
2157 textfield_->SetFocusable(true);
2160 TEST_F(TextfieldTouchSelectionTest, TapOnSelection) {
2161 InitTextfield();
2162 textfield_->SetText(ASCIIToUTF16("hello world"));
2163 gfx::Range sel_range(2, 7);
2164 gfx::Range tap_range(5, 5);
2165 gfx::Rect tap_rect =
2166 GetCursorBounds(gfx::SelectionModel(tap_range, gfx::CURSOR_FORWARD));
2167 gfx::Point tap_point = tap_rect.CenterPoint();
2169 // Select range |sel_range| and check if touch selection handles are not
2170 // present and correct range is selected.
2171 textfield_->SetSelectionRange(sel_range);
2172 gfx::Range range;
2173 textfield_->GetSelectionRange(&range);
2174 EXPECT_FALSE(test_api_->touch_selection_controller());
2175 EXPECT_EQ(sel_range, range);
2177 // Tap on selection and check if touch selectoin handles are shown, but
2178 // selection range is not modified.
2179 Tap(tap_point);
2180 textfield_->GetSelectionRange(&range);
2181 EXPECT_TRUE(test_api_->touch_selection_controller());
2182 EXPECT_EQ(sel_range, range);
2184 // Tap again on selection and check if touch selection handles are still
2185 // present and selection is changed to a cursor at tap location.
2186 Tap(tap_point);
2187 textfield_->GetSelectionRange(&range);
2188 EXPECT_TRUE(test_api_->touch_selection_controller());
2189 EXPECT_EQ(tap_range, range);
2192 } // namespace views