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"
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/accessibility/ax_view_state.h"
16 #include "ui/base/clipboard/clipboard.h"
17 #include "ui/base/clipboard/scoped_clipboard_writer.h"
18 #include "ui/base/dragdrop/drag_drop_types.h"
19 #include "ui/base/ime/input_method_base.h"
20 #include "ui/base/ime/input_method_delegate.h"
21 #include "ui/base/ime/input_method_factory.h"
22 #include "ui/base/ime/text_input_client.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/ui_base_switches.h"
25 #include "ui/base/ui_base_switches_util.h"
26 #include "ui/events/event.h"
27 #include "ui/events/event_processor.h"
28 #include "ui/events/event_utils.h"
29 #include "ui/events/keycodes/keyboard_codes.h"
30 #include "ui/gfx/render_text.h"
31 #include "ui/strings/grit/ui_strings.h"
32 #include "ui/views/controls/textfield/textfield_controller.h"
33 #include "ui/views/controls/textfield/textfield_model.h"
34 #include "ui/views/controls/textfield/textfield_test_api.h"
35 #include "ui/views/focus/focus_manager.h"
36 #include "ui/views/test/test_views_delegate.h"
37 #include "ui/views/test/views_test_base.h"
38 #include "ui/views/test/widget_test.h"
39 #include "ui/views/widget/widget.h"
43 #include "base/win/windows_version.h"
46 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
47 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
51 #include "ui/events/event_utils.h"
54 using base::ASCIIToUTF16
;
55 using base::UTF8ToUTF16
;
56 using base::WideToUTF16
;
58 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
62 const base::char16 kHebrewLetterSamekh
= 0x05E1;
64 class MockInputMethod
: public ui::InputMethodBase
{
67 ~MockInputMethod() override
;
69 // Overridden from InputMethod:
70 bool OnUntranslatedIMEMessage(const base::NativeEvent
& event
,
71 NativeEventResult
* result
) override
;
72 bool DispatchKeyEvent(const ui::KeyEvent
& key
) override
;
73 void OnTextInputTypeChanged(const ui::TextInputClient
* client
) override
;
74 void OnCaretBoundsChanged(const ui::TextInputClient
* client
) override
{}
75 void CancelComposition(const ui::TextInputClient
* client
) override
;
76 void OnInputLocaleChanged() override
{}
77 std::string
GetInputLocale() override
;
78 bool IsCandidatePopupOpen() const override
;
79 void ShowImeIfNeeded() override
{}
81 bool untranslated_ime_message_called() const {
82 return untranslated_ime_message_called_
;
84 bool text_input_type_changed() const { return text_input_type_changed_
; }
85 bool cancel_composition_called() const { return cancel_composition_called_
; }
87 // Clears all internal states and result.
90 void SetCompositionTextForNextKey(const ui::CompositionText
& composition
);
91 void SetResultTextForNextKey(const base::string16
& result
);
94 // Overridden from InputMethodBase.
95 void OnWillChangeFocusedClient(ui::TextInputClient
* focused_before
,
96 ui::TextInputClient
* focused
) override
;
98 // Clears boolean states defined below.
101 // Whether a mock composition or result is scheduled for the next key event.
102 bool HasComposition();
104 // Clears only composition information and result text.
105 void ClearComposition();
107 // Composition information for the next key event. It'll be cleared
108 // automatically after dispatching the next key event.
109 ui::CompositionText composition_
;
111 // Result text for the next key event. It'll be cleared automatically after
112 // dispatching the next key event.
113 base::string16 result_text_
;
115 // Record call state of corresponding methods. They will be set to false
116 // automatically before dispatching a key event.
117 bool untranslated_ime_message_called_
;
118 bool text_input_type_changed_
;
119 bool cancel_composition_called_
;
121 DISALLOW_COPY_AND_ASSIGN(MockInputMethod
);
124 MockInputMethod::MockInputMethod()
125 : untranslated_ime_message_called_(false),
126 text_input_type_changed_(false),
127 cancel_composition_called_(false) {
130 MockInputMethod::~MockInputMethod() {
133 bool MockInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent
& event
,
134 NativeEventResult
* result
) {
136 *result
= NativeEventResult();
140 bool MockInputMethod::DispatchKeyEvent(const ui::KeyEvent
& key
) {
141 // Checks whether the key event is from EventGenerator on Windows which will
142 // generate key event for WM_CHAR.
143 // The MockInputMethod will insert char on WM_KEYDOWN so ignore WM_CHAR here.
144 if (key
.is_char() && key
.HasNativeEvent())
147 bool handled
= !IsTextInputTypeNone() && HasComposition();
150 DCHECK(!key
.is_char());
151 ui::KeyEvent
mock_key(ui::ET_KEY_PRESSED
, ui::VKEY_PROCESSKEY
, key
.flags());
152 DispatchKeyEventPostIME(mock_key
);
154 DispatchKeyEventPostIME(key
);
157 ui::TextInputClient
* client
= GetTextInputClient();
160 if (result_text_
.length())
161 client
->InsertText(result_text_
);
162 if (composition_
.text
.length())
163 client
->SetCompositionText(composition_
);
165 client
->ClearCompositionText();
166 } else if (key
.type() == ui::ET_KEY_PRESSED
) {
167 base::char16 ch
= key
.GetCharacter();
169 client
->InsertChar(ch
, key
.flags());
177 void MockInputMethod::OnTextInputTypeChanged(
178 const ui::TextInputClient
* client
) {
179 if (IsTextInputClientFocused(client
))
180 text_input_type_changed_
= true;
181 InputMethodBase::OnTextInputTypeChanged(client
);
184 void MockInputMethod::CancelComposition(const ui::TextInputClient
* client
) {
185 if (IsTextInputClientFocused(client
)) {
186 cancel_composition_called_
= true;
191 std::string
MockInputMethod::GetInputLocale() {
195 bool MockInputMethod::IsCandidatePopupOpen() const {
199 void MockInputMethod::OnWillChangeFocusedClient(
200 ui::TextInputClient
* focused_before
,
201 ui::TextInputClient
* focused
) {
202 ui::TextInputClient
* client
= GetTextInputClient();
203 if (client
&& client
->HasCompositionText())
204 client
->ConfirmCompositionText();
208 void MockInputMethod::Clear() {
213 void MockInputMethod::SetCompositionTextForNextKey(
214 const ui::CompositionText
& composition
) {
215 composition_
= composition
;
218 void MockInputMethod::SetResultTextForNextKey(const base::string16
& result
) {
219 result_text_
= result
;
222 void MockInputMethod::ClearStates() {
223 untranslated_ime_message_called_
= false;
224 text_input_type_changed_
= false;
225 cancel_composition_called_
= false;
228 bool MockInputMethod::HasComposition() {
229 return composition_
.text
.length() || result_text_
.length();
232 void MockInputMethod::ClearComposition() {
233 composition_
.Clear();
234 result_text_
.clear();
237 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
238 class TestTextfield
: public views::Textfield
{
243 key_received_(false),
244 weak_ptr_factory_(this) {}
246 bool OnKeyPressed(const ui::KeyEvent
& e
) override
{
247 key_received_
= true;
249 // Since OnKeyPressed() might destroy |this|, get a weak pointer and
250 // verify it isn't null before writing the bool value to key_handled_.
251 base::WeakPtr
<TestTextfield
> textfield(weak_ptr_factory_
.GetWeakPtr());
252 bool key
= views::Textfield::OnKeyPressed(e
);
262 bool OnKeyReleased(const ui::KeyEvent
& e
) override
{
263 key_received_
= true;
264 key_handled_
= views::Textfield::OnKeyReleased(e
);
265 EXPECT_FALSE(key_handled_
); // Textfield doesn't override OnKeyReleased.
269 // ui::TextInputClient overrides:
270 void InsertChar(base::char16 ch
, int flags
) override
{
271 views::Textfield::InsertChar(ch
, flags
);
272 #if defined(OS_MACOSX)
273 // On Mac, characters are inserted directly rather than attempting to get a
274 // unicode character from the ui::KeyEvent (which isn't always possible).
275 key_received_
= true;
279 bool key_handled() const { return key_handled_
; }
280 bool key_received() const { return key_received_
; }
282 void clear() { key_received_
= key_handled_
= false; }
288 base::WeakPtrFactory
<TestTextfield
> weak_ptr_factory_
;
290 DISALLOW_COPY_AND_ASSIGN(TestTextfield
);
293 // Convenience to make constructing a GestureEvent simpler.
294 class GestureEventForTest
: public ui::GestureEvent
{
296 GestureEventForTest(int x
, int y
, ui::GestureEventDetails details
)
297 : GestureEvent(x
, y
, 0, base::TimeDelta(), details
) {}
300 DISALLOW_COPY_AND_ASSIGN(GestureEventForTest
);
303 // This controller will happily destroy the target textfield passed on
304 // construction when a key event is triggered.
305 class TextfieldDestroyerController
: public views::TextfieldController
{
307 explicit TextfieldDestroyerController(views::Textfield
* target
)
309 target_
->set_controller(this);
312 views::Textfield
* target() { return target_
.get(); }
314 // views::TextfieldController:
315 bool HandleKeyEvent(views::Textfield
* sender
,
316 const ui::KeyEvent
& key_event
) override
{
323 scoped_ptr
<views::Textfield
> target_
;
326 base::string16
GetClipboardText(ui::ClipboardType type
) {
328 ui::Clipboard::GetForCurrentThread()->ReadText(type
, &text
);
332 void SetClipboardText(ui::ClipboardType type
, const std::string
& text
) {
333 ui::ScopedClipboardWriter(type
).WriteText(ASCIIToUTF16(text
));
340 class TextfieldTest
: public ViewsTestBase
, public TextfieldController
{
347 on_before_user_action_(0),
348 on_after_user_action_(0),
349 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST
) {
350 input_method_
= new MockInputMethod();
351 ui::SetUpInputMethodForTesting(input_method_
);
355 void TearDown() override
{
358 ViewsTestBase::TearDown();
361 ui::ClipboardType
GetAndResetCopiedToClipboard() {
362 ui::ClipboardType clipboard_type
= copied_to_clipboard_
;
363 copied_to_clipboard_
= ui::CLIPBOARD_TYPE_LAST
;
364 return clipboard_type
;
367 // TextfieldController:
368 void ContentsChanged(Textfield
* sender
,
369 const base::string16
& new_contents
) override
{
370 // Paste calls TextfieldController::ContentsChanged() explicitly even if the
371 // paste action did not change the content. So |new_contents| may match
372 // |last_contents_|. For more info, see http://crbug.com/79002
373 last_contents_
= new_contents
;
376 void OnBeforeUserAction(Textfield
* sender
) override
{
377 ++on_before_user_action_
;
380 void OnAfterUserAction(Textfield
* sender
) override
{
381 ++on_after_user_action_
;
384 void OnAfterCutOrCopy(ui::ClipboardType clipboard_type
) override
{
385 copied_to_clipboard_
= clipboard_type
;
388 void InitTextfield() {
392 void InitTextfields(int count
) {
393 ASSERT_FALSE(textfield_
);
394 textfield_
= new TestTextfield();
395 textfield_
->set_controller(this);
396 widget_
= new Widget();
398 // The widget type must be an activatable type, and we don't want to worry
399 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS.
400 Widget::InitParams params
=
401 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
403 params
.bounds
= gfx::Rect(100, 100, 100, 100);
404 widget_
->Init(params
);
405 input_method_
->SetDelegate(
406 test::WidgetTest::GetInputMethodDelegateForWidget(widget_
));
407 View
* container
= new View();
408 widget_
->SetContentsView(container
);
409 container
->AddChildView(textfield_
);
410 textfield_
->SetBoundsRect(params
.bounds
);
411 textfield_
->set_id(1);
412 test_api_
.reset(new TextfieldTestApi(textfield_
));
414 for (int i
= 1; i
< count
; i
++) {
415 Textfield
* textfield
= new Textfield();
416 container
->AddChildView(textfield
);
417 textfield
->set_id(i
+ 1);
420 model_
= test_api_
->model();
421 model_
->ClearEditHistory();
423 // Since the window type is activatable, showing the widget will also
424 // activate it. Calling Activate directly is insufficient, since that does
425 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the
426 // widget and the textfield must have focus to properly handle input.
428 textfield_
->RequestFocus();
430 // On Mac, activation is asynchronous since desktop widgets are used. We
431 // don't want parallel tests to steal active status either, so fake it.
432 #if defined(OS_MACOSX) && !defined(USE_AURA)
433 fake_activation_
= test::WidgetTest::FakeWidgetIsActiveAlways();
437 ui::MenuModel
* GetContextMenuModel() {
438 test_api_
->UpdateContextMenu();
439 return test_api_
->context_menu_contents();
442 // True if native Mac keystrokes should be used (to avoid ifdef litter).
443 bool TestingNativeMac() {
444 #if defined(OS_MACOSX)
452 void SendKeyEvent(ui::KeyboardCode key_code
,
455 bool control_or_command
,
457 bool control
= control_or_command
;
458 bool command
= false;
460 // By default, swap control and command for native events on Mac. This
461 // handles most cases.
462 if (TestingNativeMac())
463 std::swap(control
, command
);
465 int flags
= (alt
? ui::EF_ALT_DOWN
: 0) | (shift
? ui::EF_SHIFT_DOWN
: 0) |
466 (control
? ui::EF_CONTROL_DOWN
: 0) |
467 (command
? ui::EF_COMMAND_DOWN
: 0) |
468 (caps_lock
? ui::EF_CAPS_LOCK_DOWN
: 0);
470 // TODO(shuchen): making EventGenerator support input method and using
471 // EventGenerator here. crbug.com/512315.
472 ui::KeyEvent
event(ui::ET_KEY_PRESSED
, key_code
, flags
);
473 input_method_
->DispatchKeyEvent(event
);
476 void SendKeyEvent(ui::KeyboardCode key_code
,
478 bool control_or_command
) {
479 SendKeyEvent(key_code
, false, shift
, control_or_command
, false);
482 void SendKeyEvent(ui::KeyboardCode key_code
) {
483 SendKeyEvent(key_code
, false, false);
486 void SendKeyEvent(base::char16 ch
) {
488 ui::KeyboardCode code
=
489 ch
== ' ' ? ui::VKEY_SPACE
:
490 static_cast<ui::KeyboardCode
>(ui::VKEY_A
+ ch
- 'a');
493 // For unicode characters, assume they come from IME rather than the
494 // keyboard. So they are dispatched directly to the input method.
495 ui::KeyEvent
event(ch
, ui::VKEY_UNKNOWN
, ui::EF_NONE
);
496 input_method_
->DispatchKeyEvent(event
);
500 // Sends a platform-specific move (and select) to start of line.
501 void SendHomeEvent(bool shift
) {
502 if (TestingNativeMac()) {
503 // Use Cmd+Left on native Mac. An RTL-agnostic "end" doesn't have a
504 // default key-binding on Mac.
505 SendKeyEvent(ui::VKEY_LEFT
, shift
/* shift */, true /* command */);
508 SendKeyEvent(ui::VKEY_HOME
, shift
/* shift */, false /* control */);
511 // Sends a platform-specific move (and select) to end of line.
512 void SendEndEvent(bool shift
) {
513 if (TestingNativeMac()) {
514 SendKeyEvent(ui::VKEY_RIGHT
, shift
, true); // Cmd+Right.
517 SendKeyEvent(ui::VKEY_END
, shift
, false);
520 // Sends {delete, move, select} word {forward, backward}.
521 void SendWordEvent(ui::KeyboardCode key
, bool shift
) {
525 if (TestingNativeMac()) {
526 // Use Alt+Left/Right/Backspace on native Mac.
530 SendKeyEvent(key
, alt
, shift
, control
, caps
);
533 // Sends Shift+Delete if supported, otherwise Cmd+X again.
534 void SendAlternateCut() {
535 if (TestingNativeMac())
536 SendKeyEvent(ui::VKEY_X
, false, true);
538 SendKeyEvent(ui::VKEY_DELETE
, true, false);
541 // Sends Ctrl+Insert if supported, otherwise Cmd+C again.
542 void SendAlternateCopy() {
543 if (TestingNativeMac())
544 SendKeyEvent(ui::VKEY_C
, false, true);
546 SendKeyEvent(ui::VKEY_INSERT
, false, true);
549 // Sends Shift+Insert if supported, otherwise Cmd+V again.
550 void SendAlternatePaste() {
551 if (TestingNativeMac())
552 SendKeyEvent(ui::VKEY_V
, false, true);
554 SendKeyEvent(ui::VKEY_INSERT
, true, false);
557 View
* GetFocusedView() {
558 return widget_
->GetFocusManager()->GetFocusedView();
561 int GetCursorPositionX(int cursor_pos
) {
562 return test_api_
->GetRenderText()->GetCursorBounds(
563 gfx::SelectionModel(cursor_pos
, gfx::CURSOR_FORWARD
), false).x();
566 // Get the current cursor bounds.
567 gfx::Rect
GetCursorBounds() {
568 return test_api_
->GetRenderText()->GetUpdatedCursorBounds();
571 // Get the cursor bounds of |sel|.
572 gfx::Rect
GetCursorBounds(const gfx::SelectionModel
& sel
) {
573 return test_api_
->GetRenderText()->GetCursorBounds(sel
, true);
576 gfx::Rect
GetDisplayRect() {
577 return test_api_
->GetRenderText()->display_rect();
580 // Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and
581 // y-axis is in the middle of |bound|'s vertical range.
582 void MouseClick(const gfx::Rect bound
, int x_offset
) {
583 gfx::Point
point(bound
.x() + x_offset
, bound
.y() + bound
.height() / 2);
584 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, point
, point
,
585 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
586 ui::EF_LEFT_MOUSE_BUTTON
);
587 textfield_
->OnMousePressed(click
);
588 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, point
, point
,
589 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
590 ui::EF_LEFT_MOUSE_BUTTON
);
591 textfield_
->OnMouseReleased(release
);
594 // This is to avoid double/triple click.
595 void NonClientMouseClick() {
596 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
597 ui::EventTimeForNow(),
598 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_NON_CLIENT
,
599 ui::EF_LEFT_MOUSE_BUTTON
);
600 textfield_
->OnMousePressed(click
);
601 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, gfx::Point(), gfx::Point(),
602 ui::EventTimeForNow(),
603 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_NON_CLIENT
,
604 ui::EF_LEFT_MOUSE_BUTTON
);
605 textfield_
->OnMouseReleased(release
);
608 void VerifyTextfieldContextMenuContents(bool textfield_has_selection
,
610 ui::MenuModel
* menu
) {
611 EXPECT_EQ(can_undo
, menu
->IsEnabledAt(0 /* UNDO */));
612 EXPECT_TRUE(menu
->IsEnabledAt(1 /* Separator */));
613 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(2 /* CUT */));
614 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(3 /* COPY */));
615 EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
).empty(),
616 menu
->IsEnabledAt(4 /* PASTE */));
617 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(5 /* DELETE */));
618 EXPECT_TRUE(menu
->IsEnabledAt(6 /* Separator */));
619 EXPECT_TRUE(menu
->IsEnabledAt(7 /* SELECT ALL */));
622 // We need widget to populate wrapper class.
625 TestTextfield
* textfield_
;
626 scoped_ptr
<TextfieldTestApi
> test_api_
;
627 TextfieldModel
* model_
;
629 // The string from Controller::ContentsChanged callback.
630 base::string16 last_contents_
;
632 // For testing input method related behaviors.
633 MockInputMethod
* input_method_
;
635 // Indicates how many times OnBeforeUserAction() is called.
636 int on_before_user_action_
;
638 // Indicates how many times OnAfterUserAction() is called.
639 int on_after_user_action_
;
642 ui::ClipboardType copied_to_clipboard_
;
643 scoped_ptr
<test::WidgetTest::FakeActivation
> fake_activation_
;
645 DISALLOW_COPY_AND_ASSIGN(TextfieldTest
);
648 TEST_F(TextfieldTest
, ModelChangesTest
) {
651 // TextfieldController::ContentsChanged() shouldn't be called when changing
652 // text programmatically.
653 last_contents_
.clear();
654 textfield_
->SetText(ASCIIToUTF16("this is"));
656 EXPECT_STR_EQ("this is", model_
->text());
657 EXPECT_STR_EQ("this is", textfield_
->text());
658 EXPECT_TRUE(last_contents_
.empty());
660 textfield_
->AppendText(ASCIIToUTF16(" a test"));
661 EXPECT_STR_EQ("this is a test", model_
->text());
662 EXPECT_STR_EQ("this is a test", textfield_
->text());
663 EXPECT_TRUE(last_contents_
.empty());
665 EXPECT_EQ(base::string16(), textfield_
->GetSelectedText());
666 textfield_
->SelectAll(false);
667 EXPECT_STR_EQ("this is a test", textfield_
->GetSelectedText());
668 EXPECT_TRUE(last_contents_
.empty());
671 TEST_F(TextfieldTest
, KeyTest
) {
673 // Event flags: key, alt, shift, ctrl, caps-lock.
674 SendKeyEvent(ui::VKEY_T
, false, true, false, false);
675 SendKeyEvent(ui::VKEY_E
, false, false, false, false);
676 SendKeyEvent(ui::VKEY_X
, false, true, false, true);
677 SendKeyEvent(ui::VKEY_T
, false, false, false, true);
678 SendKeyEvent(ui::VKEY_1
, false, true, false, false);
679 SendKeyEvent(ui::VKEY_1
, false, false, false, false);
680 SendKeyEvent(ui::VKEY_1
, false, true, false, true);
681 SendKeyEvent(ui::VKEY_1
, false, false, false, true);
683 // On Mac, Caps+Shift remains uppercase.
684 if (TestingNativeMac())
685 EXPECT_STR_EQ("TeXT!1!1", textfield_
->text());
687 EXPECT_STR_EQ("TexT!1!1", textfield_
->text());
690 TEST_F(TextfieldTest
, ControlAndSelectTest
) {
691 // Insert a test string in a textfield.
693 textfield_
->SetText(ASCIIToUTF16("one two three"));
694 SendHomeEvent(false);
695 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
696 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
697 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
699 EXPECT_STR_EQ("one", textfield_
->GetSelectedText());
702 SendWordEvent(ui::VKEY_RIGHT
, true);
703 EXPECT_STR_EQ("one two", textfield_
->GetSelectedText());
704 SendWordEvent(ui::VKEY_RIGHT
, true);
705 EXPECT_STR_EQ("one two three", textfield_
->GetSelectedText());
706 SendWordEvent(ui::VKEY_LEFT
, true);
707 EXPECT_STR_EQ("one two ", textfield_
->GetSelectedText());
708 SendWordEvent(ui::VKEY_LEFT
, true);
709 EXPECT_STR_EQ("one ", textfield_
->GetSelectedText());
711 // Replace the selected text.
712 SendKeyEvent(ui::VKEY_Z
, true, false);
713 SendKeyEvent(ui::VKEY_E
, true, false);
714 SendKeyEvent(ui::VKEY_R
, true, false);
715 SendKeyEvent(ui::VKEY_O
, true, false);
716 SendKeyEvent(ui::VKEY_SPACE
, false, false);
717 EXPECT_STR_EQ("ZERO two three", textfield_
->text());
720 EXPECT_STR_EQ("two three", textfield_
->GetSelectedText());
722 EXPECT_STR_EQ("ZERO ", textfield_
->GetSelectedText());
725 TEST_F(TextfieldTest
, InsertionDeletionTest
) {
726 // Insert a test string in a textfield.
728 for (size_t i
= 0; i
< 10; i
++)
729 SendKeyEvent(static_cast<ui::KeyboardCode
>(ui::VKEY_A
+ i
));
730 EXPECT_STR_EQ("abcdefghij", textfield_
->text());
732 // Test the delete and backspace keys.
733 textfield_
->SelectRange(gfx::Range(5));
734 for (int i
= 0; i
< 3; i
++)
735 SendKeyEvent(ui::VKEY_BACK
);
736 EXPECT_STR_EQ("abfghij", textfield_
->text());
737 for (int i
= 0; i
< 3; i
++)
738 SendKeyEvent(ui::VKEY_DELETE
);
739 EXPECT_STR_EQ("abij", textfield_
->text());
741 // Select all and replace with "k".
742 textfield_
->SelectAll(false);
743 SendKeyEvent(ui::VKEY_K
);
744 EXPECT_STR_EQ("k", textfield_
->text());
746 // Delete the previous word from cursor.
748 textfield_
->SetText(ASCIIToUTF16("one two three four"));
750 SendWordEvent(ui::VKEY_BACK
, shift
);
751 EXPECT_STR_EQ("one two three ", textfield_
->text());
753 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
755 SendWordEvent(ui::VKEY_LEFT
, shift
);
757 SendWordEvent(ui::VKEY_BACK
, shift
);
758 #if defined(OS_LINUX)
759 EXPECT_STR_EQ("three ", textfield_
->text());
761 EXPECT_STR_EQ("one three ", textfield_
->text());
764 // Delete the next word from cursor.
765 textfield_
->SetText(ASCIIToUTF16("one two three four"));
767 SendHomeEvent(shift
);
768 SendWordEvent(ui::VKEY_DELETE
, shift
);
769 EXPECT_STR_EQ(" two three four", textfield_
->text());
771 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
773 SendWordEvent(ui::VKEY_RIGHT
, shift
);
775 SendWordEvent(ui::VKEY_DELETE
, shift
);
776 #if defined(OS_LINUX)
777 EXPECT_STR_EQ(" two", textfield_
->text());
779 EXPECT_STR_EQ(" two four", textfield_
->text());
783 TEST_F(TextfieldTest
, PasswordTest
) {
785 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
786 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
787 EXPECT_TRUE(textfield_
->enabled());
788 EXPECT_TRUE(textfield_
->IsFocusable());
790 last_contents_
.clear();
791 textfield_
->SetText(ASCIIToUTF16("password"));
792 // Ensure text() and the callback returns the actual text instead of "*".
793 EXPECT_STR_EQ("password", textfield_
->text());
794 EXPECT_TRUE(last_contents_
.empty());
795 model_
->SelectAll(false);
796 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "foo");
798 // Cut and copy should be disabled.
799 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
800 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
801 SendKeyEvent(ui::VKEY_X
, false, true);
802 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
803 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
804 SendKeyEvent(ui::VKEY_C
, false, true);
806 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
807 EXPECT_STR_EQ("password", textfield_
->text());
808 // [Shift]+[Delete] should just delete without copying text to the clipboard.
809 textfield_
->SelectAll(false);
810 SendKeyEvent(ui::VKEY_DELETE
, true, false);
812 // Paste should work normally.
813 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
814 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
815 SendKeyEvent(ui::VKEY_V
, false, true);
816 SendAlternatePaste();
817 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
818 EXPECT_STR_EQ("foofoofoo", textfield_
->text());
821 TEST_F(TextfieldTest
, TextInputType
) {
825 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT
, textfield_
->GetTextInputType());
828 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_URL
);
829 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL
, textfield_
->GetTextInputType());
830 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
831 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
833 // Readonly textfields have type NONE
834 textfield_
->SetReadOnly(true);
835 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, textfield_
->GetTextInputType());
837 textfield_
->SetReadOnly(false);
838 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
840 // As do disabled textfields
841 textfield_
->SetEnabled(false);
842 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, textfield_
->GetTextInputType());
844 textfield_
->SetEnabled(true);
845 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
848 TEST_F(TextfieldTest
, OnKeyPress
) {
851 // Character keys are handled by the input method.
852 SendKeyEvent(ui::VKEY_A
);
853 EXPECT_TRUE(textfield_
->key_received());
854 EXPECT_FALSE(textfield_
->key_handled());
857 // Arrow keys and home/end are handled by the textfield.
858 SendKeyEvent(ui::VKEY_LEFT
);
859 EXPECT_TRUE(textfield_
->key_received());
860 EXPECT_TRUE(textfield_
->key_handled());
863 SendKeyEvent(ui::VKEY_RIGHT
);
864 EXPECT_TRUE(textfield_
->key_received());
865 EXPECT_TRUE(textfield_
->key_handled());
868 const bool shift
= false;
869 SendHomeEvent(shift
);
870 EXPECT_TRUE(textfield_
->key_received());
871 EXPECT_TRUE(textfield_
->key_handled());
875 EXPECT_TRUE(textfield_
->key_received());
876 EXPECT_TRUE(textfield_
->key_handled());
879 // F20, up/down key won't be handled.
880 SendKeyEvent(ui::VKEY_F20
);
881 #if defined(OS_MACOSX)
882 // On Mac, key combinations that don't map to editing commands are forwarded
883 // on to the next responder, usually ending up at the window, which will beep.
884 EXPECT_FALSE(textfield_
->key_received());
886 EXPECT_TRUE(textfield_
->key_received());
888 EXPECT_FALSE(textfield_
->key_handled());
891 SendKeyEvent(ui::VKEY_UP
);
892 EXPECT_TRUE(textfield_
->key_received());
893 EXPECT_FALSE(textfield_
->key_handled());
896 SendKeyEvent(ui::VKEY_DOWN
);
897 EXPECT_TRUE(textfield_
->key_received());
898 EXPECT_FALSE(textfield_
->key_handled());
902 // Tests that default key bindings are handled even with a delegate installed.
903 TEST_F(TextfieldTest
, OnKeyPressBinding
) {
906 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
907 // Install a TextEditKeyBindingsDelegateAuraLinux that does nothing.
908 class TestDelegate
: public ui::TextEditKeyBindingsDelegateAuraLinux
{
911 ~TestDelegate() override
{}
914 const ui::Event
& event
,
915 std::vector
<ui::TextEditCommandAuraLinux
>* commands
) override
{
920 DISALLOW_COPY_AND_ASSIGN(TestDelegate
);
923 TestDelegate delegate
;
924 ui::SetTextEditKeyBindingsDelegate(&delegate
);
927 SendKeyEvent(ui::VKEY_A
, false, false);
928 EXPECT_STR_EQ("a", textfield_
->text());
931 // Undo/Redo command keys are handled by the textfield.
932 SendKeyEvent(ui::VKEY_Z
, false, true);
933 EXPECT_TRUE(textfield_
->key_received());
934 EXPECT_TRUE(textfield_
->key_handled());
935 EXPECT_TRUE(textfield_
->text().empty());
938 SendKeyEvent(ui::VKEY_Z
, true, true);
939 EXPECT_TRUE(textfield_
->key_received());
940 EXPECT_TRUE(textfield_
->key_handled());
941 EXPECT_STR_EQ("a", textfield_
->text());
944 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
945 ui::SetTextEditKeyBindingsDelegate(NULL
);
949 TEST_F(TextfieldTest
, CursorMovement
) {
952 // Test with trailing whitespace.
953 textfield_
->SetText(ASCIIToUTF16("one two hre "));
955 // Send the cursor at the end.
956 SendKeyEvent(ui::VKEY_END
);
958 // Ctrl+Left should move the cursor just before the last word.
959 const bool shift
= false;
960 SendWordEvent(ui::VKEY_LEFT
, shift
);
961 SendKeyEvent(ui::VKEY_T
);
962 EXPECT_STR_EQ("one two thre ", textfield_
->text());
963 EXPECT_STR_EQ("one two thre ", last_contents_
);
965 // Ctrl+Right should move the cursor to the end of the last word.
966 SendWordEvent(ui::VKEY_RIGHT
, shift
);
967 SendKeyEvent(ui::VKEY_E
);
968 EXPECT_STR_EQ("one two three ", textfield_
->text());
969 EXPECT_STR_EQ("one two three ", last_contents_
);
971 // Ctrl+Right again should move the cursor to the end.
972 SendWordEvent(ui::VKEY_RIGHT
, shift
);
973 SendKeyEvent(ui::VKEY_BACK
);
974 EXPECT_STR_EQ("one two three", textfield_
->text());
975 EXPECT_STR_EQ("one two three", last_contents_
);
977 // Test with leading whitespace.
978 textfield_
->SetText(ASCIIToUTF16(" ne two"));
980 // Send the cursor at the beginning.
981 SendHomeEvent(shift
);
983 // Ctrl+Right, then Ctrl+Left should move the cursor to the beginning of the
985 SendWordEvent(ui::VKEY_RIGHT
, shift
);
986 SendWordEvent(ui::VKEY_LEFT
, shift
);
987 SendKeyEvent(ui::VKEY_O
);
988 EXPECT_STR_EQ(" one two", textfield_
->text());
989 EXPECT_STR_EQ(" one two", last_contents_
);
991 // Ctrl+Left to move the cursor to the beginning of the first word.
992 SendWordEvent(ui::VKEY_LEFT
, shift
);
993 // Ctrl+Left again should move the cursor back to the very beginning.
994 SendWordEvent(ui::VKEY_LEFT
, shift
);
995 SendKeyEvent(ui::VKEY_DELETE
);
996 EXPECT_STR_EQ("one two", textfield_
->text());
997 EXPECT_STR_EQ("one two", last_contents_
);
1000 TEST_F(TextfieldTest
, FocusTraversalTest
) {
1002 textfield_
->RequestFocus();
1004 EXPECT_EQ(1, GetFocusedView()->id());
1005 widget_
->GetFocusManager()->AdvanceFocus(false);
1006 EXPECT_EQ(2, GetFocusedView()->id());
1007 widget_
->GetFocusManager()->AdvanceFocus(false);
1008 EXPECT_EQ(3, GetFocusedView()->id());
1009 // Cycle back to the first textfield.
1010 widget_
->GetFocusManager()->AdvanceFocus(false);
1011 EXPECT_EQ(1, GetFocusedView()->id());
1013 widget_
->GetFocusManager()->AdvanceFocus(true);
1014 EXPECT_EQ(3, GetFocusedView()->id());
1015 widget_
->GetFocusManager()->AdvanceFocus(true);
1016 EXPECT_EQ(2, GetFocusedView()->id());
1017 widget_
->GetFocusManager()->AdvanceFocus(true);
1018 EXPECT_EQ(1, GetFocusedView()->id());
1019 // Cycle back to the last textfield.
1020 widget_
->GetFocusManager()->AdvanceFocus(true);
1021 EXPECT_EQ(3, GetFocusedView()->id());
1023 // Request focus should still work.
1024 textfield_
->RequestFocus();
1025 EXPECT_EQ(1, GetFocusedView()->id());
1027 // Test if clicking on textfield view sets the focus.
1028 widget_
->GetFocusManager()->AdvanceFocus(true);
1029 EXPECT_EQ(3, GetFocusedView()->id());
1030 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
1031 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1032 ui::EF_LEFT_MOUSE_BUTTON
);
1033 textfield_
->OnMousePressed(click
);
1034 EXPECT_EQ(1, GetFocusedView()->id());
1036 // Tab/Shift+Tab should also cycle focus, not insert a tab character.
1037 SendKeyEvent(ui::VKEY_TAB
, false, false);
1038 EXPECT_EQ(2, GetFocusedView()->id());
1039 SendKeyEvent(ui::VKEY_TAB
, false, false);
1040 EXPECT_EQ(3, GetFocusedView()->id());
1041 // Cycle back to the first textfield.
1042 SendKeyEvent(ui::VKEY_TAB
, false, false);
1043 EXPECT_EQ(1, GetFocusedView()->id());
1045 SendKeyEvent(ui::VKEY_TAB
, true, false);
1046 EXPECT_EQ(3, GetFocusedView()->id());
1047 SendKeyEvent(ui::VKEY_TAB
, true, false);
1048 EXPECT_EQ(2, GetFocusedView()->id());
1049 SendKeyEvent(ui::VKEY_TAB
, true, false);
1050 EXPECT_EQ(1, GetFocusedView()->id());
1051 // Cycle back to the last textfield.
1052 SendKeyEvent(ui::VKEY_TAB
, true, false);
1053 EXPECT_EQ(3, GetFocusedView()->id());
1056 TEST_F(TextfieldTest
, ContextMenuDisplayTest
) {
1058 EXPECT_TRUE(textfield_
->context_menu_controller());
1059 textfield_
->SetText(ASCIIToUTF16("hello world"));
1060 ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE
);
1061 textfield_
->ClearEditHistory();
1062 EXPECT_TRUE(GetContextMenuModel());
1063 VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
1065 textfield_
->SelectAll(false);
1066 VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel());
1068 SendKeyEvent(ui::VKEY_T
);
1069 VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel());
1071 textfield_
->SelectAll(false);
1072 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1074 // Exercise the "paste enabled?" check in the verifier.
1075 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1076 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1079 TEST_F(TextfieldTest
, DoubleAndTripleClickTest
) {
1081 textfield_
->SetText(ASCIIToUTF16("hello world"));
1082 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
1083 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1084 ui::EF_LEFT_MOUSE_BUTTON
);
1085 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, gfx::Point(), gfx::Point(),
1086 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1087 ui::EF_LEFT_MOUSE_BUTTON
);
1088 ui::MouseEvent
double_click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
1089 ui::EventTimeForNow(),
1090 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_DOUBLE_CLICK
,
1091 ui::EF_LEFT_MOUSE_BUTTON
);
1093 // Test for double click.
1094 textfield_
->OnMousePressed(click
);
1095 textfield_
->OnMouseReleased(release
);
1096 EXPECT_TRUE(textfield_
->GetSelectedText().empty());
1097 textfield_
->OnMousePressed(double_click
);
1098 textfield_
->OnMouseReleased(release
);
1099 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
1101 // Test for triple click.
1102 textfield_
->OnMousePressed(click
);
1103 textfield_
->OnMouseReleased(release
);
1104 EXPECT_STR_EQ("hello world", textfield_
->GetSelectedText());
1106 // Another click should reset back to double click.
1107 textfield_
->OnMousePressed(click
);
1108 textfield_
->OnMouseReleased(release
);
1109 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
1112 TEST_F(TextfieldTest
, DragToSelect
) {
1114 textfield_
->SetText(ASCIIToUTF16("hello world"));
1115 const int kStart
= GetCursorPositionX(5);
1116 const int kEnd
= 500;
1117 gfx::Point
start_point(kStart
, 0);
1118 gfx::Point
end_point(kEnd
, 0);
1119 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, start_point
, start_point
,
1120 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1121 ui::EF_LEFT_MOUSE_BUTTON
);
1122 ui::MouseEvent
click_b(ui::ET_MOUSE_PRESSED
, end_point
, end_point
,
1123 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1124 ui::EF_LEFT_MOUSE_BUTTON
);
1125 ui::MouseEvent
drag_left(ui::ET_MOUSE_DRAGGED
, gfx::Point(), gfx::Point(),
1126 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1127 ui::MouseEvent
drag_right(ui::ET_MOUSE_DRAGGED
, end_point
, end_point
,
1128 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1129 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, end_point
, end_point
,
1130 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1131 ui::EF_LEFT_MOUSE_BUTTON
);
1132 textfield_
->OnMousePressed(click_a
);
1133 EXPECT_TRUE(textfield_
->GetSelectedText().empty());
1134 // Check that dragging left selects the beginning of the string.
1135 textfield_
->OnMouseDragged(drag_left
);
1136 base::string16 text_left
= textfield_
->GetSelectedText();
1137 EXPECT_STR_EQ("hello", text_left
);
1138 // Check that dragging right selects the rest of the string.
1139 textfield_
->OnMouseDragged(drag_right
);
1140 base::string16 text_right
= textfield_
->GetSelectedText();
1141 EXPECT_STR_EQ(" world", text_right
);
1142 // Check that releasing in the same location does not alter the selection.
1143 textfield_
->OnMouseReleased(release
);
1144 EXPECT_EQ(text_right
, textfield_
->GetSelectedText());
1145 // Check that dragging from beyond the text length works too.
1146 textfield_
->OnMousePressed(click_b
);
1147 textfield_
->OnMouseDragged(drag_left
);
1148 textfield_
->OnMouseReleased(release
);
1149 EXPECT_EQ(textfield_
->text(), textfield_
->GetSelectedText());
1153 TEST_F(TextfieldTest
, DragAndDrop_AcceptDrop
) {
1155 textfield_
->SetText(ASCIIToUTF16("hello world"));
1157 ui::OSExchangeData data
;
1158 base::string16
string(ASCIIToUTF16("string "));
1159 data
.SetString(string
);
1161 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1163 // Ensure that disabled textfields do not accept drops.
1164 textfield_
->SetEnabled(false);
1165 EXPECT_FALSE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1166 EXPECT_EQ(0, formats
);
1167 EXPECT_TRUE(custom_formats
.empty());
1168 EXPECT_FALSE(textfield_
->CanDrop(data
));
1169 textfield_
->SetEnabled(true);
1171 // Ensure that read-only textfields do not accept drops.
1172 textfield_
->SetReadOnly(true);
1173 EXPECT_FALSE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1174 EXPECT_EQ(0, formats
);
1175 EXPECT_TRUE(custom_formats
.empty());
1176 EXPECT_FALSE(textfield_
->CanDrop(data
));
1177 textfield_
->SetReadOnly(false);
1179 // Ensure that enabled and editable textfields do accept drops.
1180 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1181 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1182 EXPECT_TRUE(custom_formats
.empty());
1183 EXPECT_TRUE(textfield_
->CanDrop(data
));
1184 gfx::Point
drop_point(GetCursorPositionX(6), 0);
1185 ui::DropTargetEvent
drop(data
, drop_point
, drop_point
,
1186 ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_MOVE
);
1187 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_MOVE
,
1188 textfield_
->OnDragUpdated(drop
));
1189 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
, textfield_
->OnPerformDrop(drop
));
1190 EXPECT_STR_EQ("hello string world", textfield_
->text());
1192 // Ensure that textfields do not accept non-OSExchangeData::STRING types.
1193 ui::OSExchangeData bad_data
;
1194 bad_data
.SetFilename(base::FilePath(FILE_PATH_LITERAL("x")));
1195 ui::OSExchangeData::CustomFormat fmt
= ui::Clipboard::GetBitmapFormatType();
1196 bad_data
.SetPickledData(fmt
, base::Pickle());
1197 bad_data
.SetFileContents(base::FilePath(L
"x"), "x");
1198 bad_data
.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org"));
1199 ui::OSExchangeData::DownloadFileInfo
download(base::FilePath(), NULL
);
1200 bad_data
.SetDownloadFileInfo(download
);
1201 EXPECT_FALSE(textfield_
->CanDrop(bad_data
));
1205 TEST_F(TextfieldTest
, DragAndDrop_InitiateDrag
) {
1207 textfield_
->SetText(ASCIIToUTF16("hello string world"));
1209 // Ensure the textfield will provide selected text for drag data.
1210 base::string16 string
;
1211 ui::OSExchangeData data
;
1212 const gfx::Range
kStringRange(6, 12);
1213 textfield_
->SelectRange(kStringRange
);
1214 const gfx::Point
kStringPoint(GetCursorPositionX(9), 0);
1215 textfield_
->WriteDragDataForView(NULL
, kStringPoint
, &data
);
1216 EXPECT_TRUE(data
.GetString(&string
));
1217 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1219 // Ensure that disabled textfields do not support drag operations.
1220 textfield_
->SetEnabled(false);
1221 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1222 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1223 textfield_
->SetEnabled(true);
1224 // Ensure that textfields without selections do not support drag operations.
1225 textfield_
->ClearSelection();
1226 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1227 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1228 textfield_
->SelectRange(kStringRange
);
1229 // Ensure that password textfields do not support drag operations.
1230 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
1231 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1232 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1233 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT
);
1234 // Ensure that textfields only initiate drag operations inside the selection.
1235 ui::MouseEvent
press_event(ui::ET_MOUSE_PRESSED
, kStringPoint
, kStringPoint
,
1236 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1237 ui::EF_LEFT_MOUSE_BUTTON
);
1238 textfield_
->OnMousePressed(press_event
);
1239 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1240 textfield_
->GetDragOperationsForView(NULL
, gfx::Point()));
1241 EXPECT_FALSE(textfield_
->CanStartDragForView(NULL
, gfx::Point(),
1243 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
,
1244 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1245 EXPECT_TRUE(textfield_
->CanStartDragForView(NULL
, kStringPoint
,
1247 // Ensure that textfields support local moves.
1248 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1249 textfield_
->GetDragOperationsForView(textfield_
, kStringPoint
));
1252 TEST_F(TextfieldTest
, DragAndDrop_ToTheRight
) {
1254 textfield_
->SetText(ASCIIToUTF16("hello world"));
1256 base::string16 string
;
1257 ui::OSExchangeData data
;
1260 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1262 // Start dragging "ello".
1263 textfield_
->SelectRange(gfx::Range(1, 5));
1264 gfx::Point
point(GetCursorPositionX(3), 0);
1265 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, point
, point
,
1266 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1267 ui::EF_LEFT_MOUSE_BUTTON
);
1268 textfield_
->OnMousePressed(click_a
);
1269 EXPECT_TRUE(textfield_
->CanStartDragForView(textfield_
, click_a
.location(),
1271 operations
= textfield_
->GetDragOperationsForView(textfield_
,
1272 click_a
.location());
1273 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1275 textfield_
->WriteDragDataForView(NULL
, click_a
.location(), &data
);
1276 EXPECT_TRUE(data
.GetString(&string
));
1277 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1278 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1279 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1280 EXPECT_TRUE(custom_formats
.empty());
1282 // Drop "ello" after "w".
1283 const gfx::Point
kDropPoint(GetCursorPositionX(7), 0);
1284 EXPECT_TRUE(textfield_
->CanDrop(data
));
1285 ui::DropTargetEvent
drop_a(data
, kDropPoint
, kDropPoint
, operations
);
1286 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop_a
));
1287 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnPerformDrop(drop_a
));
1288 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1289 textfield_
->OnDragDone();
1291 // Undo/Redo the drag&drop change.
1292 SendKeyEvent(ui::VKEY_Z
, false, true);
1293 EXPECT_STR_EQ("hello world", textfield_
->text());
1294 SendKeyEvent(ui::VKEY_Z
, false, true);
1295 EXPECT_STR_EQ("", textfield_
->text());
1296 SendKeyEvent(ui::VKEY_Z
, false, true);
1297 EXPECT_STR_EQ("", textfield_
->text());
1298 SendKeyEvent(ui::VKEY_Z
, true, true);
1299 EXPECT_STR_EQ("hello world", textfield_
->text());
1300 SendKeyEvent(ui::VKEY_Z
, true, true);
1301 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1302 SendKeyEvent(ui::VKEY_Z
, true, true);
1303 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1306 TEST_F(TextfieldTest
, DragAndDrop_ToTheLeft
) {
1308 textfield_
->SetText(ASCIIToUTF16("hello world"));
1310 base::string16 string
;
1311 ui::OSExchangeData data
;
1314 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1316 // Start dragging " worl".
1317 textfield_
->SelectRange(gfx::Range(5, 10));
1318 gfx::Point
point(GetCursorPositionX(7), 0);
1319 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, point
, point
,
1320 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1321 ui::EF_LEFT_MOUSE_BUTTON
);
1322 textfield_
->OnMousePressed(click_a
);
1323 EXPECT_TRUE(textfield_
->CanStartDragForView(textfield_
, click_a
.location(),
1325 operations
= textfield_
->GetDragOperationsForView(textfield_
,
1326 click_a
.location());
1327 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1329 textfield_
->WriteDragDataForView(NULL
, click_a
.location(), &data
);
1330 EXPECT_TRUE(data
.GetString(&string
));
1331 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1332 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1333 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1334 EXPECT_TRUE(custom_formats
.empty());
1336 // Drop " worl" after "h".
1337 EXPECT_TRUE(textfield_
->CanDrop(data
));
1338 gfx::Point
drop_point(GetCursorPositionX(1), 0);
1339 ui::DropTargetEvent
drop_a(data
, drop_point
, drop_point
, operations
);
1340 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop_a
));
1341 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnPerformDrop(drop_a
));
1342 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1343 textfield_
->OnDragDone();
1345 // Undo/Redo the drag&drop change.
1346 SendKeyEvent(ui::VKEY_Z
, false, true);
1347 EXPECT_STR_EQ("hello world", textfield_
->text());
1348 SendKeyEvent(ui::VKEY_Z
, false, true);
1349 EXPECT_STR_EQ("", textfield_
->text());
1350 SendKeyEvent(ui::VKEY_Z
, false, true);
1351 EXPECT_STR_EQ("", textfield_
->text());
1352 SendKeyEvent(ui::VKEY_Z
, true, true);
1353 EXPECT_STR_EQ("hello world", textfield_
->text());
1354 SendKeyEvent(ui::VKEY_Z
, true, true);
1355 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1356 SendKeyEvent(ui::VKEY_Z
, true, true);
1357 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1360 TEST_F(TextfieldTest
, DragAndDrop_Canceled
) {
1362 textfield_
->SetText(ASCIIToUTF16("hello world"));
1364 // Start dragging "worl".
1365 textfield_
->SelectRange(gfx::Range(6, 10));
1366 gfx::Point
point(GetCursorPositionX(8), 0);
1367 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, point
, point
,
1368 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1369 ui::EF_LEFT_MOUSE_BUTTON
);
1370 textfield_
->OnMousePressed(click
);
1371 ui::OSExchangeData data
;
1372 textfield_
->WriteDragDataForView(NULL
, click
.location(), &data
);
1373 EXPECT_TRUE(textfield_
->CanDrop(data
));
1374 // Drag the text over somewhere valid, outside the current selection.
1375 gfx::Point
drop_point(GetCursorPositionX(2), 0);
1376 ui::DropTargetEvent
drop(data
, drop_point
, drop_point
,
1377 ui::DragDropTypes::DRAG_MOVE
);
1378 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop
));
1379 // "Cancel" the drag, via move and release over the selection, and OnDragDone.
1380 gfx::Point
drag_point(GetCursorPositionX(9), 0);
1381 ui::MouseEvent
drag(ui::ET_MOUSE_DRAGGED
, drag_point
, drag_point
,
1382 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1383 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, drag_point
, drag_point
,
1384 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1385 ui::EF_LEFT_MOUSE_BUTTON
);
1386 textfield_
->OnMouseDragged(drag
);
1387 textfield_
->OnMouseReleased(release
);
1388 textfield_
->OnDragDone();
1389 EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_
->text());
1392 TEST_F(TextfieldTest
, ReadOnlyTest
) {
1394 textfield_
->SetText(ASCIIToUTF16("read only"));
1395 textfield_
->SetReadOnly(true);
1396 EXPECT_TRUE(textfield_
->enabled());
1397 EXPECT_TRUE(textfield_
->IsFocusable());
1400 SendHomeEvent(shift
);
1401 EXPECT_EQ(0U, textfield_
->GetCursorPosition());
1402 SendEndEvent(shift
);
1403 EXPECT_EQ(9U, textfield_
->GetCursorPosition());
1405 SendKeyEvent(ui::VKEY_LEFT
, shift
, false);
1406 EXPECT_EQ(8U, textfield_
->GetCursorPosition());
1407 SendWordEvent(ui::VKEY_LEFT
, shift
);
1408 EXPECT_EQ(5U, textfield_
->GetCursorPosition());
1410 SendWordEvent(ui::VKEY_LEFT
, shift
);
1411 EXPECT_EQ(0U, textfield_
->GetCursorPosition());
1412 EXPECT_STR_EQ("read ", textfield_
->GetSelectedText());
1413 textfield_
->SelectAll(false);
1414 EXPECT_STR_EQ("read only", textfield_
->GetSelectedText());
1416 // Cut should be disabled.
1417 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1418 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
1419 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
1420 SendKeyEvent(ui::VKEY_X
, false, true);
1422 EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1423 EXPECT_STR_EQ("read only", textfield_
->text());
1425 // Paste should be disabled.
1426 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
1427 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
1428 SendKeyEvent(ui::VKEY_V
, false, true);
1429 SendAlternatePaste();
1430 EXPECT_STR_EQ("read only", textfield_
->text());
1432 // Copy should work normally.
1433 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1434 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
1435 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
1436 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1437 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1438 SendKeyEvent(ui::VKEY_C
, false, true);
1439 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1440 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1441 SendAlternateCopy();
1442 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1444 // SetText should work even in read only mode.
1445 textfield_
->SetText(ASCIIToUTF16(" four five six "));
1446 EXPECT_STR_EQ(" four five six ", textfield_
->text());
1448 textfield_
->SelectAll(false);
1449 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1451 // Text field is unmodifiable and selection shouldn't change.
1452 SendKeyEvent(ui::VKEY_DELETE
);
1453 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1454 SendKeyEvent(ui::VKEY_BACK
);
1455 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1456 SendKeyEvent(ui::VKEY_T
);
1457 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1460 TEST_F(TextfieldTest
, TextInputClientTest
) {
1462 ui::TextInputClient
* client
= textfield_
;
1463 EXPECT_TRUE(client
);
1464 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT
, client
->GetTextInputType());
1466 textfield_
->SetText(ASCIIToUTF16("0123456789"));
1468 EXPECT_TRUE(client
->GetTextRange(&range
));
1469 EXPECT_EQ(0U, range
.start());
1470 EXPECT_EQ(10U, range
.end());
1472 EXPECT_TRUE(client
->SetSelectionRange(gfx::Range(1, 4)));
1473 EXPECT_TRUE(client
->GetSelectionRange(&range
));
1474 EXPECT_EQ(gfx::Range(1, 4), range
);
1476 base::string16 substring
;
1477 EXPECT_TRUE(client
->GetTextFromRange(range
, &substring
));
1478 EXPECT_STR_EQ("123", substring
);
1480 EXPECT_TRUE(client
->DeleteRange(range
));
1481 EXPECT_STR_EQ("0456789", textfield_
->text());
1483 ui::CompositionText composition
;
1484 composition
.text
= UTF8ToUTF16("321");
1485 // Set composition through input method.
1486 input_method_
->Clear();
1487 input_method_
->SetCompositionTextForNextKey(composition
);
1488 textfield_
->clear();
1490 on_before_user_action_
= on_after_user_action_
= 0;
1492 // Send a key to trigger MockInputMethod::DispatchKeyEvent(). Note the
1493 // specific VKEY isn't used (MockInputMethod will mock a ui::VKEY_PROCESSKEY
1494 // whenever it has a test composition). However, on Mac, it can't be a letter
1495 // (e.g. VKEY_A) since all native character events on Mac are unicode events
1496 // and don't have a meaningful ui::KeyEvent that would trigger
1497 // DispatchKeyEvent().
1498 SendKeyEvent(ui::VKEY_RETURN
);
1500 EXPECT_TRUE(textfield_
->key_received());
1501 EXPECT_FALSE(textfield_
->key_handled());
1502 EXPECT_TRUE(client
->HasCompositionText());
1503 EXPECT_TRUE(client
->GetCompositionTextRange(&range
));
1504 EXPECT_STR_EQ("0321456789", textfield_
->text());
1505 EXPECT_EQ(gfx::Range(1, 4), range
);
1506 EXPECT_EQ(1, on_before_user_action_
);
1507 EXPECT_EQ(1, on_after_user_action_
);
1509 input_method_
->SetResultTextForNextKey(UTF8ToUTF16("123"));
1510 on_before_user_action_
= on_after_user_action_
= 0;
1511 textfield_
->clear();
1512 SendKeyEvent(ui::VKEY_RETURN
);
1513 EXPECT_TRUE(textfield_
->key_received());
1514 EXPECT_FALSE(textfield_
->key_handled());
1515 EXPECT_FALSE(client
->HasCompositionText());
1516 EXPECT_FALSE(input_method_
->cancel_composition_called());
1517 EXPECT_STR_EQ("0123456789", textfield_
->text());
1518 EXPECT_EQ(1, on_before_user_action_
);
1519 EXPECT_EQ(1, on_after_user_action_
);
1521 input_method_
->Clear();
1522 input_method_
->SetCompositionTextForNextKey(composition
);
1523 textfield_
->clear();
1524 SendKeyEvent(ui::VKEY_RETURN
);
1525 EXPECT_TRUE(client
->HasCompositionText());
1526 EXPECT_STR_EQ("0123321456789", textfield_
->text());
1528 on_before_user_action_
= on_after_user_action_
= 0;
1529 textfield_
->clear();
1530 SendKeyEvent(ui::VKEY_RIGHT
);
1531 EXPECT_FALSE(client
->HasCompositionText());
1532 EXPECT_TRUE(input_method_
->cancel_composition_called());
1533 EXPECT_TRUE(textfield_
->key_received());
1534 EXPECT_TRUE(textfield_
->key_handled());
1535 EXPECT_STR_EQ("0123321456789", textfield_
->text());
1536 EXPECT_EQ(8U, textfield_
->GetCursorPosition());
1537 EXPECT_EQ(1, on_before_user_action_
);
1538 EXPECT_EQ(1, on_after_user_action_
);
1540 textfield_
->clear();
1541 textfield_
->SetText(ASCIIToUTF16("0123456789"));
1542 EXPECT_TRUE(client
->SetSelectionRange(gfx::Range(5, 5)));
1543 client
->ExtendSelectionAndDelete(4, 2);
1544 EXPECT_STR_EQ("0789", textfield_
->text());
1546 // On{Before,After}UserAction should be called by whatever user action
1547 // triggers clearing or setting a selection if appropriate.
1548 on_before_user_action_
= on_after_user_action_
= 0;
1549 textfield_
->clear();
1550 textfield_
->ClearSelection();
1551 textfield_
->SelectAll(false);
1552 EXPECT_EQ(0, on_before_user_action_
);
1553 EXPECT_EQ(0, on_after_user_action_
);
1555 input_method_
->Clear();
1557 // Changing the Textfield to readonly shouldn't change the input client, since
1558 // it's still required for selections and clipboard copy.
1559 ui::TextInputClient
* text_input_client
= textfield_
;
1560 EXPECT_TRUE(text_input_client
);
1561 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1562 textfield_
->SetReadOnly(true);
1563 EXPECT_TRUE(input_method_
->text_input_type_changed());
1564 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1566 input_method_
->Clear();
1567 textfield_
->SetReadOnly(false);
1568 EXPECT_TRUE(input_method_
->text_input_type_changed());
1569 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1571 input_method_
->Clear();
1572 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
1573 EXPECT_TRUE(input_method_
->text_input_type_changed());
1576 TEST_F(TextfieldTest
, UndoRedoTest
) {
1578 SendKeyEvent(ui::VKEY_A
);
1579 EXPECT_STR_EQ("a", textfield_
->text());
1580 SendKeyEvent(ui::VKEY_Z
, false, true);
1581 EXPECT_STR_EQ("", textfield_
->text());
1582 SendKeyEvent(ui::VKEY_Z
, false, true);
1583 EXPECT_STR_EQ("", textfield_
->text());
1584 SendKeyEvent(ui::VKEY_Z
, true, true);
1585 EXPECT_STR_EQ("a", textfield_
->text());
1586 SendKeyEvent(ui::VKEY_Z
, true, true);
1587 EXPECT_STR_EQ("a", textfield_
->text());
1590 textfield_
->AppendText(ASCIIToUTF16("b"));
1591 last_contents_
.clear(); // AppendText doesn't call ContentsChanged.
1592 EXPECT_STR_EQ("ab", textfield_
->text());
1593 SendKeyEvent(ui::VKEY_Z
, false, true);
1594 EXPECT_STR_EQ("a", textfield_
->text());
1595 SendKeyEvent(ui::VKEY_Z
, true, true);
1596 EXPECT_STR_EQ("ab", textfield_
->text());
1599 SendKeyEvent(ui::VKEY_C
);
1600 // Undo'ing append moves the cursor to the end for now.
1601 // A no-op SetText won't add a new edit; see TextfieldModel::SetText.
1602 EXPECT_STR_EQ("abc", textfield_
->text());
1603 textfield_
->SetText(ASCIIToUTF16("abc"));
1604 EXPECT_STR_EQ("abc", textfield_
->text());
1605 SendKeyEvent(ui::VKEY_Z
, false, true);
1606 EXPECT_STR_EQ("ab", textfield_
->text());
1607 SendKeyEvent(ui::VKEY_Z
, true, true);
1608 EXPECT_STR_EQ("abc", textfield_
->text());
1609 SendKeyEvent(ui::VKEY_Z
, true, true);
1610 EXPECT_STR_EQ("abc", textfield_
->text());
1611 textfield_
->SetText(ASCIIToUTF16("123"));
1612 textfield_
->SetText(ASCIIToUTF16("123"));
1613 EXPECT_STR_EQ("123", textfield_
->text());
1614 SendKeyEvent(ui::VKEY_END
, false, false);
1615 SendKeyEvent(ui::VKEY_4
, false, false);
1616 EXPECT_STR_EQ("1234", textfield_
->text());
1617 last_contents_
.clear();
1618 SendKeyEvent(ui::VKEY_Z
, false, true);
1619 EXPECT_STR_EQ("123", textfield_
->text());
1620 SendKeyEvent(ui::VKEY_Z
, false, true);
1621 // the insert edit "c" and set edit "123" are merged to single edit,
1622 // so text becomes "ab" after undo.
1623 EXPECT_STR_EQ("ab", textfield_
->text());
1624 SendKeyEvent(ui::VKEY_Z
, false, true);
1625 EXPECT_STR_EQ("a", textfield_
->text());
1626 SendKeyEvent(ui::VKEY_Z
, true, true);
1627 EXPECT_STR_EQ("ab", textfield_
->text());
1628 SendKeyEvent(ui::VKEY_Z
, true, true);
1629 EXPECT_STR_EQ("123", textfield_
->text());
1630 SendKeyEvent(ui::VKEY_Z
, true, true);
1631 EXPECT_STR_EQ("1234", textfield_
->text());
1633 // Undoing to the same text shouldn't call ContentsChanged.
1634 SendKeyEvent(ui::VKEY_A
, false, true); // select all
1635 SendKeyEvent(ui::VKEY_A
);
1636 EXPECT_STR_EQ("a", textfield_
->text());
1637 SendKeyEvent(ui::VKEY_B
);
1638 SendKeyEvent(ui::VKEY_C
);
1639 EXPECT_STR_EQ("abc", textfield_
->text());
1640 SendKeyEvent(ui::VKEY_Z
, false, true);
1641 EXPECT_STR_EQ("1234", textfield_
->text());
1642 SendKeyEvent(ui::VKEY_Z
, true, true);
1643 EXPECT_STR_EQ("abc", textfield_
->text());
1646 SendKeyEvent(ui::VKEY_BACK
);
1647 EXPECT_STR_EQ("ab", textfield_
->text());
1648 SendHomeEvent(false);
1649 SendKeyEvent(ui::VKEY_DELETE
);
1650 EXPECT_STR_EQ("b", textfield_
->text());
1651 SendKeyEvent(ui::VKEY_A
, false, true);
1652 SendKeyEvent(ui::VKEY_DELETE
);
1653 EXPECT_STR_EQ("", textfield_
->text());
1654 SendKeyEvent(ui::VKEY_Z
, false, true);
1655 EXPECT_STR_EQ("b", textfield_
->text());
1656 SendKeyEvent(ui::VKEY_Z
, false, true);
1657 EXPECT_STR_EQ("ab", textfield_
->text());
1658 SendKeyEvent(ui::VKEY_Z
, false, true);
1659 EXPECT_STR_EQ("abc", textfield_
->text());
1660 SendKeyEvent(ui::VKEY_Z
, true, true);
1661 EXPECT_STR_EQ("ab", textfield_
->text());
1662 SendKeyEvent(ui::VKEY_Z
, true, true);
1663 EXPECT_STR_EQ("b", textfield_
->text());
1664 SendKeyEvent(ui::VKEY_Z
, true, true);
1665 EXPECT_STR_EQ("", textfield_
->text());
1666 SendKeyEvent(ui::VKEY_Z
, true, true);
1667 EXPECT_STR_EQ("", textfield_
->text());
1670 // Most platforms support Ctrl+Y as an alternative to Ctrl+Shift+Z, but on Mac
1671 // that is bound to "Show full history", so is not mapped as an editing
1672 // command. So, on Mac, send Cmd+Shift+Z.
1673 #if !defined(OS_MACOSX)
1675 // Test that Ctrl+Y works for Redo, as well as Ctrl+Shift+Z.
1676 TEST_F(TextfieldTest
, RedoWithCtrlY
) {
1678 SendKeyEvent(ui::VKEY_A
);
1679 EXPECT_STR_EQ("a", textfield_
->text());
1680 SendKeyEvent(ui::VKEY_Z
, false, true);
1681 EXPECT_STR_EQ("", textfield_
->text());
1682 SendKeyEvent(ui::VKEY_Y
, false, true);
1683 EXPECT_STR_EQ("a", textfield_
->text());
1684 SendKeyEvent(ui::VKEY_Z
, false, true);
1685 EXPECT_STR_EQ("", textfield_
->text());
1686 SendKeyEvent(ui::VKEY_Z
, true, true);
1687 EXPECT_STR_EQ("a", textfield_
->text());
1690 #endif // !defined(OS_MACOSX)
1692 TEST_F(TextfieldTest
, CutCopyPaste
) {
1695 // Ensure IDS_APP_CUT cuts.
1696 textfield_
->SetText(ASCIIToUTF16("123"));
1697 textfield_
->SelectAll(false);
1698 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
1699 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
1700 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1701 EXPECT_STR_EQ("", textfield_
->text());
1702 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1704 // Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
1705 textfield_
->SetText(ASCIIToUTF16("456"));
1706 textfield_
->SelectAll(false);
1707 SendKeyEvent(ui::VKEY_X
, true, false, true, false);
1708 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1709 EXPECT_STR_EQ("456", textfield_
->text());
1710 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1711 SendKeyEvent(ui::VKEY_X
, false, true);
1712 EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1713 EXPECT_STR_EQ("", textfield_
->text());
1714 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1716 // Ensure [Shift]+[Delete] cuts.
1717 textfield_
->SetText(ASCIIToUTF16("123"));
1718 textfield_
->SelectAll(false);
1720 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1721 EXPECT_STR_EQ("", textfield_
->text());
1722 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1724 // Ensure IDS_APP_COPY copies.
1725 textfield_
->SetText(ASCIIToUTF16("789"));
1726 textfield_
->SelectAll(false);
1727 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
1728 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
1729 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1730 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1732 // Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
1733 textfield_
->SetText(ASCIIToUTF16("012"));
1734 textfield_
->SelectAll(false);
1735 SendKeyEvent(ui::VKEY_C
, true, false, true, false);
1736 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1737 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1738 SendKeyEvent(ui::VKEY_C
, false, true);
1739 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1740 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1742 // Ensure [Ctrl]+[Insert] copies.
1743 textfield_
->SetText(ASCIIToUTF16("345"));
1744 textfield_
->SelectAll(false);
1745 SendAlternateCopy();
1746 EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1747 EXPECT_STR_EQ("345", textfield_
->text());
1748 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1750 // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
1751 // also ensure that [Ctrl]+[Alt]+[V] does nothing.
1752 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "abc");
1753 textfield_
->SetText(base::string16());
1754 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
1755 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
1756 EXPECT_STR_EQ("abc", textfield_
->text());
1757 SendKeyEvent(ui::VKEY_V
, false, true);
1758 EXPECT_STR_EQ("abcabc", textfield_
->text());
1759 SendAlternatePaste();
1760 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1761 SendKeyEvent(ui::VKEY_V
, true, false, true, false);
1762 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1764 // Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
1765 textfield_
->SelectAll(false);
1766 SendKeyEvent(ui::VKEY_INSERT
, true, true);
1767 EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1768 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1769 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1772 TEST_F(TextfieldTest
, OvertypeMode
) {
1774 // Overtype mode should be disabled (no-op [Insert]).
1775 textfield_
->SetText(ASCIIToUTF16("2"));
1776 const bool shift
= false;
1777 SendHomeEvent(shift
);
1778 // Note: On Mac, there is no insert key. Insert sends kVK_Help. Currently,
1779 // since there is no overtype on toolkit-views, the behavior happens to match.
1780 // However, there's no enable-overtype equivalent key combination on OSX.
1781 SendKeyEvent(ui::VKEY_INSERT
);
1782 SendKeyEvent(ui::VKEY_1
, false, false);
1783 EXPECT_STR_EQ("12", textfield_
->text());
1786 TEST_F(TextfieldTest
, TextCursorDisplayTest
) {
1788 // LTR-RTL string in LTR context.
1790 EXPECT_STR_EQ("a", textfield_
->text());
1791 int x
= GetCursorBounds().x();
1795 EXPECT_STR_EQ("ab", textfield_
->text());
1796 x
= GetCursorBounds().x();
1797 EXPECT_LT(prev_x
, x
);
1800 SendKeyEvent(0x05E1);
1801 EXPECT_EQ(WideToUTF16(L
"ab\x05E1"), textfield_
->text());
1802 x
= GetCursorBounds().x();
1803 EXPECT_GE(1, std::abs(x
- prev_x
));
1805 SendKeyEvent(0x05E2);
1806 EXPECT_EQ(WideToUTF16(L
"ab\x05E1\x5E2"), textfield_
->text());
1807 x
= GetCursorBounds().x();
1808 EXPECT_GE(1, std::abs(x
- prev_x
));
1811 SendKeyEvent(ui::VKEY_A
, false, true);
1812 SendKeyEvent(ui::VKEY_DELETE
);
1814 // RTL-LTR string in LTR context.
1815 SendKeyEvent(0x05E1);
1816 EXPECT_EQ(WideToUTF16(L
"\x05E1"), textfield_
->text());
1817 x
= GetCursorBounds().x();
1818 EXPECT_EQ(GetDisplayRect().x(), x
);
1821 SendKeyEvent(0x05E2);
1822 EXPECT_EQ(WideToUTF16(L
"\x05E1\x05E2"), textfield_
->text());
1823 x
= GetCursorBounds().x();
1824 EXPECT_GE(1, std::abs(x
- prev_x
));
1827 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"a"), textfield_
->text());
1828 x
= GetCursorBounds().x();
1829 EXPECT_LT(prev_x
, x
);
1833 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"ab"), textfield_
->text());
1834 x
= GetCursorBounds().x();
1835 EXPECT_LT(prev_x
, x
);
1838 TEST_F(TextfieldTest
, TextCursorDisplayInRTLTest
) {
1839 std::string locale
= l10n_util::GetApplicationLocale("");
1840 base::i18n::SetICUDefaultLocale("he");
1843 // LTR-RTL string in RTL context.
1845 EXPECT_STR_EQ("a", textfield_
->text());
1846 int x
= GetCursorBounds().x();
1847 EXPECT_EQ(GetDisplayRect().right() - 1, x
);
1851 EXPECT_STR_EQ("ab", textfield_
->text());
1852 x
= GetCursorBounds().x();
1853 EXPECT_GE(1, std::abs(x
- prev_x
));
1855 SendKeyEvent(0x05E1);
1856 EXPECT_EQ(WideToUTF16(L
"ab\x05E1"), textfield_
->text());
1857 x
= GetCursorBounds().x();
1858 EXPECT_GT(prev_x
, x
);
1861 SendKeyEvent(0x05E2);
1862 EXPECT_EQ(WideToUTF16(L
"ab\x05E1\x5E2"), textfield_
->text());
1863 x
= GetCursorBounds().x();
1864 EXPECT_GT(prev_x
, x
);
1867 SendKeyEvent(ui::VKEY_A
, false, true);
1868 SendKeyEvent(ui::VKEY_DELETE
);
1870 // RTL-LTR string in RTL context.
1871 SendKeyEvent(0x05E1);
1872 EXPECT_EQ(WideToUTF16(L
"\x05E1"), textfield_
->text());
1873 x
= GetCursorBounds().x();
1876 SendKeyEvent(0x05E2);
1877 EXPECT_EQ(WideToUTF16(L
"\x05E1\x05E2"), textfield_
->text());
1878 x
= GetCursorBounds().x();
1879 EXPECT_GT(prev_x
, x
);
1883 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"a"), textfield_
->text());
1884 x
= GetCursorBounds().x();
1885 EXPECT_GE(1, std::abs(x
- prev_x
));
1889 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"ab"), textfield_
->text());
1890 x
= GetCursorBounds().x();
1891 EXPECT_GE(1, std::abs(x
- prev_x
));
1894 base::i18n::SetICUDefaultLocale(locale
);
1897 TEST_F(TextfieldTest
, HitInsideTextAreaTest
) {
1899 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
1900 std::vector
<gfx::Rect
> cursor_bounds
;
1902 // Save each cursor bound.
1903 gfx::SelectionModel
sel(0, gfx::CURSOR_FORWARD
);
1904 cursor_bounds
.push_back(GetCursorBounds(sel
));
1906 sel
= gfx::SelectionModel(1, gfx::CURSOR_BACKWARD
);
1907 gfx::Rect bound
= GetCursorBounds(sel
);
1908 sel
= gfx::SelectionModel(1, gfx::CURSOR_FORWARD
);
1909 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1910 cursor_bounds
.push_back(bound
);
1912 // Check that a cursor at the end of the Latin portion of the text is at the
1913 // same position as a cursor placed at the end of the RTL Hebrew portion.
1914 sel
= gfx::SelectionModel(2, gfx::CURSOR_BACKWARD
);
1915 bound
= GetCursorBounds(sel
);
1916 sel
= gfx::SelectionModel(4, gfx::CURSOR_BACKWARD
);
1917 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1918 cursor_bounds
.push_back(bound
);
1920 sel
= gfx::SelectionModel(3, gfx::CURSOR_BACKWARD
);
1921 bound
= GetCursorBounds(sel
);
1922 sel
= gfx::SelectionModel(3, gfx::CURSOR_FORWARD
);
1923 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1924 cursor_bounds
.push_back(bound
);
1926 sel
= gfx::SelectionModel(2, gfx::CURSOR_FORWARD
);
1927 bound
= GetCursorBounds(sel
);
1928 sel
= gfx::SelectionModel(4, gfx::CURSOR_FORWARD
);
1929 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1930 cursor_bounds
.push_back(bound
);
1932 // Expected cursor position when clicking left and right of each character.
1933 size_t cursor_pos_expected
[] = {0, 1, 1, 2, 4, 3, 3, 2};
1936 for (int i
= 0; i
< static_cast<int>(cursor_bounds
.size() - 1); ++i
) {
1937 int half_width
= (cursor_bounds
[i
+ 1].x() - cursor_bounds
[i
].x()) / 2;
1938 MouseClick(cursor_bounds
[i
], half_width
/ 2);
1939 EXPECT_EQ(cursor_pos_expected
[index
++], textfield_
->GetCursorPosition());
1941 // To avoid trigger double click. Not using sleep() since it takes longer
1942 // for the test to run if using sleep().
1943 NonClientMouseClick();
1945 MouseClick(cursor_bounds
[i
+ 1], - (half_width
/ 2));
1946 EXPECT_EQ(cursor_pos_expected
[index
++], textfield_
->GetCursorPosition());
1948 NonClientMouseClick();
1952 TEST_F(TextfieldTest
, HitOutsideTextAreaTest
) {
1955 // LTR-RTL string in LTR context.
1956 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
1958 const bool shift
= false;
1959 SendHomeEvent(shift
);
1960 gfx::Rect bound
= GetCursorBounds();
1961 MouseClick(bound
, -10);
1962 EXPECT_EQ(bound
, GetCursorBounds());
1964 SendEndEvent(shift
);
1965 bound
= GetCursorBounds();
1966 MouseClick(bound
, 10);
1967 EXPECT_EQ(bound
, GetCursorBounds());
1969 NonClientMouseClick();
1971 // RTL-LTR string in LTR context.
1972 textfield_
->SetText(WideToUTF16(L
"\x05E1\x5E2" L
"ab"));
1974 SendHomeEvent(shift
);
1975 bound
= GetCursorBounds();
1976 MouseClick(bound
, 10);
1977 EXPECT_EQ(bound
, GetCursorBounds());
1979 SendEndEvent(shift
);
1980 bound
= GetCursorBounds();
1981 MouseClick(bound
, -10);
1982 EXPECT_EQ(bound
, GetCursorBounds());
1985 TEST_F(TextfieldTest
, HitOutsideTextAreaInRTLTest
) {
1986 std::string locale
= l10n_util::GetApplicationLocale("");
1987 base::i18n::SetICUDefaultLocale("he");
1991 // RTL-LTR string in RTL context.
1992 textfield_
->SetText(WideToUTF16(L
"\x05E1\x5E2" L
"ab"));
1993 const bool shift
= false;
1994 SendHomeEvent(shift
);
1995 gfx::Rect bound
= GetCursorBounds();
1996 MouseClick(bound
, 10);
1997 EXPECT_EQ(bound
, GetCursorBounds());
1999 SendEndEvent(shift
);
2000 bound
= GetCursorBounds();
2001 MouseClick(bound
, -10);
2002 EXPECT_EQ(bound
, GetCursorBounds());
2004 NonClientMouseClick();
2006 // LTR-RTL string in RTL context.
2007 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
2008 SendHomeEvent(shift
);
2009 bound
= GetCursorBounds();
2010 MouseClick(bound
, -10);
2011 EXPECT_EQ(bound
, GetCursorBounds());
2013 SendEndEvent(shift
);
2014 bound
= GetCursorBounds();
2015 MouseClick(bound
, 10);
2016 EXPECT_EQ(bound
, GetCursorBounds());
2019 base::i18n::SetICUDefaultLocale(locale
);
2022 TEST_F(TextfieldTest
, OverflowTest
) {
2026 for (int i
= 0; i
< 500; ++i
)
2028 SendKeyEvent(kHebrewLetterSamekh
);
2029 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2031 // Test mouse pointing.
2032 MouseClick(GetCursorBounds(), -1);
2033 EXPECT_EQ(500U, textfield_
->GetCursorPosition());
2036 SendKeyEvent(ui::VKEY_A
, false, true);
2037 SendKeyEvent(ui::VKEY_DELETE
);
2039 for (int i
= 0; i
< 500; ++i
)
2040 SendKeyEvent(kHebrewLetterSamekh
);
2042 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2044 MouseClick(GetCursorBounds(), -1);
2045 EXPECT_EQ(501U, textfield_
->GetCursorPosition());
2048 TEST_F(TextfieldTest
, OverflowInRTLTest
) {
2049 std::string locale
= l10n_util::GetApplicationLocale("");
2050 base::i18n::SetICUDefaultLocale("he");
2055 for (int i
= 0; i
< 500; ++i
)
2057 SendKeyEvent(kHebrewLetterSamekh
);
2058 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2060 MouseClick(GetCursorBounds(), 1);
2061 EXPECT_EQ(501U, textfield_
->GetCursorPosition());
2064 SendKeyEvent(ui::VKEY_A
, false, true);
2065 SendKeyEvent(ui::VKEY_DELETE
);
2067 for (int i
= 0; i
< 500; ++i
)
2068 SendKeyEvent(kHebrewLetterSamekh
);
2070 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2072 MouseClick(GetCursorBounds(), 1);
2073 EXPECT_EQ(500U, textfield_
->GetCursorPosition());
2076 base::i18n::SetICUDefaultLocale(locale
);
2079 TEST_F(TextfieldTest
, GetCompositionCharacterBoundsTest
) {
2081 ui::CompositionText composition
;
2082 composition
.text
= UTF8ToUTF16("abc123");
2083 const uint32 char_count
= static_cast<uint32
>(composition
.text
.length());
2084 ui::TextInputClient
* client
= textfield_
;
2086 // Compare the composition character bounds with surrounding cursor bounds.
2087 for (uint32 i
= 0; i
< char_count
; ++i
) {
2088 composition
.selection
= gfx::Range(i
);
2089 client
->SetCompositionText(composition
);
2090 gfx::Point cursor_origin
= GetCursorBounds().origin();
2091 views::View::ConvertPointToScreen(textfield_
, &cursor_origin
);
2093 composition
.selection
= gfx::Range(i
+ 1);
2094 client
->SetCompositionText(composition
);
2095 gfx::Point next_cursor_bottom_left
= GetCursorBounds().bottom_left();
2096 views::View::ConvertPointToScreen(textfield_
, &next_cursor_bottom_left
);
2098 gfx::Rect character
;
2099 EXPECT_TRUE(client
->GetCompositionCharacterBounds(i
, &character
));
2100 EXPECT_EQ(character
.origin(), cursor_origin
) << " i=" << i
;
2101 EXPECT_EQ(character
.bottom_right(), next_cursor_bottom_left
) << " i=" << i
;
2104 // Return false if the index is out of range.
2106 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
, &rect
));
2107 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
+ 1, &rect
));
2108 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
+ 100, &rect
));
2111 TEST_F(TextfieldTest
, GetCompositionCharacterBounds_ComplexText
) {
2114 const base::char16 kUtf16Chars
[] = {
2117 // U+1F408 (CAT) as surrogate pair
2119 // U+5642 as Ideographic Variation Sequences
2120 0x5642, 0xDB40, 0xDD00,
2121 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences
2126 const size_t kUtf16CharsCount
= arraysize(kUtf16Chars
);
2128 ui::CompositionText composition
;
2129 composition
.text
.assign(kUtf16Chars
, kUtf16Chars
+ kUtf16CharsCount
);
2130 ui::TextInputClient
* client
= textfield_
;
2131 client
->SetCompositionText(composition
);
2133 // Make sure GetCompositionCharacterBounds never fails for index.
2134 gfx::Rect rects
[kUtf16CharsCount
];
2135 gfx::Rect prev_cursor
= GetCursorBounds();
2136 for (uint32 i
= 0; i
< kUtf16CharsCount
; ++i
)
2137 EXPECT_TRUE(client
->GetCompositionCharacterBounds(i
, &rects
[i
]));
2139 // Here we might expect the following results but it actually depends on how
2140 // Uniscribe or HarfBuzz treats them with given font.
2141 // - rects[1] == rects[2]
2142 // - rects[3] == rects[4] == rects[5]
2143 // - rects[6] == rects[7]
2146 // The word we select by double clicking should remain selected regardless of
2147 // where we drag the mouse afterwards without releasing the left button.
2148 TEST_F(TextfieldTest
, KeepInitiallySelectedWord
) {
2151 textfield_
->SetText(ASCIIToUTF16("abc def ghi"));
2153 textfield_
->SelectRange(gfx::Range(5, 5));
2154 const gfx::Rect middle_cursor
= GetCursorBounds();
2155 textfield_
->SelectRange(gfx::Range(0, 0));
2156 const gfx::Point beginning
= GetCursorBounds().origin();
2158 // Double click, but do not release the left button.
2159 MouseClick(middle_cursor
, 0);
2160 const gfx::Point
middle(middle_cursor
.x(),
2161 middle_cursor
.y() + middle_cursor
.height() / 2);
2162 ui::MouseEvent
press_event(ui::ET_MOUSE_PRESSED
, middle
, middle
,
2163 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2164 ui::EF_LEFT_MOUSE_BUTTON
);
2165 textfield_
->OnMousePressed(press_event
);
2166 EXPECT_EQ(gfx::Range(4, 7), textfield_
->GetSelectedRange());
2168 // Drag the mouse to the beginning of the textfield.
2169 ui::MouseEvent
drag_event(ui::ET_MOUSE_DRAGGED
, beginning
, beginning
,
2170 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
2171 textfield_
->OnMouseDragged(drag_event
);
2172 EXPECT_EQ(gfx::Range(7, 0), textfield_
->GetSelectedRange());
2175 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2176 // flaky: http://crbug.com/396477
2177 TEST_F(TextfieldTest
, DISABLED_SelectionClipboard
) {
2179 textfield_
->SetText(ASCIIToUTF16("0123"));
2180 gfx::Point
point_1(GetCursorPositionX(1), 0);
2181 gfx::Point
point_2(GetCursorPositionX(2), 0);
2182 gfx::Point
point_3(GetCursorPositionX(3), 0);
2183 gfx::Point
point_4(GetCursorPositionX(4), 0);
2185 // Text selected by the mouse should be placed on the selection clipboard.
2186 ui::MouseEvent
press(ui::ET_MOUSE_PRESSED
, point_1
, point_1
,
2187 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2188 ui::EF_LEFT_MOUSE_BUTTON
);
2189 textfield_
->OnMousePressed(press
);
2190 ui::MouseEvent
drag(ui::ET_MOUSE_DRAGGED
, point_3
, point_3
,
2191 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2192 ui::EF_LEFT_MOUSE_BUTTON
);
2193 textfield_
->OnMouseDragged(drag
);
2194 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, point_3
, point_3
,
2195 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2196 ui::EF_LEFT_MOUSE_BUTTON
);
2197 textfield_
->OnMouseReleased(release
);
2198 EXPECT_EQ(gfx::Range(1, 3), textfield_
->GetSelectedRange());
2199 EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2201 // Select-all should update the selection clipboard.
2202 SendKeyEvent(ui::VKEY_A
, false, true);
2203 EXPECT_EQ(gfx::Range(0, 4), textfield_
->GetSelectedRange());
2204 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2205 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2207 // Shift-click selection modifications should update the clipboard.
2208 NonClientMouseClick();
2209 ui::MouseEvent
press_2(ui::ET_MOUSE_PRESSED
, point_2
, point_2
,
2210 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2211 ui::EF_LEFT_MOUSE_BUTTON
);
2212 press_2
.set_flags(press_2
.flags() | ui::EF_SHIFT_DOWN
);
2213 #if defined(USE_X11)
2214 ui::UpdateX11EventForFlags(&press_2
);
2216 textfield_
->OnMousePressed(press_2
);
2217 ui::MouseEvent
release_2(ui::ET_MOUSE_RELEASED
, point_2
, point_2
,
2218 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2219 ui::EF_LEFT_MOUSE_BUTTON
);
2220 textfield_
->OnMouseReleased(release_2
);
2221 EXPECT_EQ(gfx::Range(0, 2), textfield_
->GetSelectedRange());
2222 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2223 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2225 // Shift-Left/Right should update the selection clipboard.
2226 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
2227 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2228 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2229 SendKeyEvent(ui::VKEY_LEFT
, true, false);
2230 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2231 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2232 SendKeyEvent(ui::VKEY_RIGHT
, true, true);
2233 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2234 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2236 // Moving the cursor without a selection should not change the clipboard.
2237 SendKeyEvent(ui::VKEY_LEFT
, false, false);
2238 EXPECT_EQ(gfx::Range(0, 0), textfield_
->GetSelectedRange());
2239 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2240 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2242 // Middle clicking should paste at the mouse (not cursor) location.
2243 // The cursor should be placed at the end of the pasted text.
2244 ui::MouseEvent
middle(ui::ET_MOUSE_PRESSED
, point_4
, point_4
,
2245 ui::EventTimeForNow(), ui::EF_MIDDLE_MOUSE_BUTTON
,
2246 ui::EF_MIDDLE_MOUSE_BUTTON
);
2247 textfield_
->OnMousePressed(middle
);
2248 EXPECT_STR_EQ("01230123", textfield_
->text());
2249 EXPECT_EQ(gfx::Range(8, 8), textfield_
->GetSelectedRange());
2250 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2252 // Middle clicking on an unfocused textfield should focus it and paste.
2253 textfield_
->GetFocusManager()->ClearFocus();
2254 EXPECT_FALSE(textfield_
->HasFocus());
2255 textfield_
->OnMousePressed(middle
);
2256 EXPECT_TRUE(textfield_
->HasFocus());
2257 EXPECT_STR_EQ("012301230123", textfield_
->text());
2258 EXPECT_EQ(gfx::Range(8, 8), textfield_
->GetSelectedRange());
2259 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2261 // Middle clicking with an empty selection clipboard should still focus.
2262 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, std::string());
2263 textfield_
->GetFocusManager()->ClearFocus();
2264 EXPECT_FALSE(textfield_
->HasFocus());
2265 textfield_
->OnMousePressed(middle
);
2266 EXPECT_TRUE(textfield_
->HasFocus());
2267 EXPECT_STR_EQ("012301230123", textfield_
->text());
2268 EXPECT_EQ(gfx::Range(4, 4), textfield_
->GetSelectedRange());
2269 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
).empty());
2271 // Middle clicking in the selection should clear the clipboard and selection.
2272 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "foo");
2273 textfield_
->SelectRange(gfx::Range(2, 6));
2274 textfield_
->OnMousePressed(middle
);
2275 EXPECT_STR_EQ("012301230123", textfield_
->text());
2276 EXPECT_EQ(gfx::Range(6, 6), textfield_
->GetSelectedRange());
2277 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
).empty());
2279 // Double and triple clicking should update the clipboard contents.
2280 textfield_
->SetText(ASCIIToUTF16("ab cd ef"));
2281 gfx::Point
word(GetCursorPositionX(4), 0);
2282 ui::MouseEvent
press_word(ui::ET_MOUSE_PRESSED
, word
, word
,
2283 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2284 ui::EF_LEFT_MOUSE_BUTTON
);
2285 textfield_
->OnMousePressed(press_word
);
2286 ui::MouseEvent
release_word(ui::ET_MOUSE_RELEASED
, word
, word
,
2287 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2288 ui::EF_LEFT_MOUSE_BUTTON
);
2289 textfield_
->OnMouseReleased(release_word
);
2290 ui::MouseEvent
double_click(ui::ET_MOUSE_PRESSED
, word
, word
,
2291 ui::EventTimeForNow(),
2292 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_DOUBLE_CLICK
,
2293 ui::EF_LEFT_MOUSE_BUTTON
);
2294 textfield_
->OnMousePressed(double_click
);
2295 textfield_
->OnMouseReleased(release_word
);
2296 EXPECT_EQ(gfx::Range(3, 5), textfield_
->GetSelectedRange());
2297 EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2298 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2299 textfield_
->OnMousePressed(press_word
);
2300 textfield_
->OnMouseReleased(release_word
);
2301 EXPECT_EQ(gfx::Range(0, 8), textfield_
->GetSelectedRange());
2302 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2303 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2305 // Selecting a range of text without any user interaction should not change
2306 // the clipboard content.
2307 textfield_
->SelectRange(gfx::Range(0, 3));
2308 EXPECT_STR_EQ("ab ", textfield_
->GetSelectedText());
2309 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2310 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2312 SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
, "other");
2313 textfield_
->SelectAll(false);
2314 EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2315 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2319 // Long_Press gesture in Textfield can initiate a drag and drop now.
2320 TEST_F(TextfieldTest
, TestLongPressInitiatesDragDrop
) {
2322 textfield_
->SetText(ASCIIToUTF16("Hello string world"));
2324 // Ensure the textfield will provide selected text for drag data.
2325 textfield_
->SelectRange(gfx::Range(6, 12));
2326 const gfx::Point
kStringPoint(GetCursorPositionX(9), 0);
2328 // Enable touch-drag-drop to make long press effective.
2329 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2330 switches::kEnableTouchDragDrop
);
2332 // Create a long press event in the selected region should start a drag.
2333 GestureEventForTest
long_press(
2336 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2337 textfield_
->OnGestureEvent(&long_press
);
2338 EXPECT_TRUE(textfield_
->CanStartDragForView(NULL
, kStringPoint
,
2342 TEST_F(TextfieldTest
, GetTextfieldBaseline_FontFallbackTest
) {
2344 textfield_
->SetText(UTF8ToUTF16("abc"));
2345 const int old_baseline
= textfield_
->GetBaseline();
2347 // Set text which may fall back to a font which has taller baseline than
2348 // the default font.
2349 textfield_
->SetText(UTF8ToUTF16("\xE0\xB9\x91"));
2350 const int new_baseline
= textfield_
->GetBaseline();
2352 // Regardless of the text, the baseline must be the same.
2353 EXPECT_EQ(new_baseline
, old_baseline
);
2356 // Tests that a textfield view can be destroyed from OnKeyEvent() on its
2357 // controller and it does not crash.
2358 TEST_F(TextfieldTest
, DestroyingTextfieldFromOnKeyEvent
) {
2361 // The controller assumes ownership of the textfield.
2362 TextfieldDestroyerController
controller(textfield_
);
2363 EXPECT_TRUE(controller
.target());
2365 // Send a key to trigger OnKeyEvent().
2366 SendKeyEvent(ui::VKEY_RETURN
);
2368 EXPECT_FALSE(controller
.target());
2371 class TextfieldTouchSelectionTest
: public TextfieldTest
{
2374 void SetUp() override
{
2375 TextfieldTest::SetUp();
2376 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2377 switches::kEnableTouchEditing
);
2381 // Simulates a complete tap.
2382 void Tap(const gfx::Point
& point
) {
2383 GestureEventForTest
begin(
2384 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_BEGIN
));
2385 textfield_
->OnGestureEvent(&begin
);
2387 GestureEventForTest
tap_down(
2388 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN
));
2389 textfield_
->OnGestureEvent(&tap_down
);
2391 GestureEventForTest
show_press(
2394 ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS
));
2395 textfield_
->OnGestureEvent(&show_press
);
2397 ui::GestureEventDetails
tap_details(ui::ET_GESTURE_TAP
);
2398 tap_details
.set_tap_count(1);
2399 GestureEventForTest
tap(point
.x(), point
.y(), tap_details
);
2400 textfield_
->OnGestureEvent(&tap
);
2402 GestureEventForTest
end(
2403 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_END
));
2404 textfield_
->OnGestureEvent(&end
);
2409 // Touch selection and dragging currently only works for chromeos.
2410 #if defined(OS_CHROMEOS)
2411 TEST_F(TextfieldTouchSelectionTest
, TouchSelectionAndDraggingTest
) {
2413 textfield_
->SetText(ASCIIToUTF16("hello world"));
2414 EXPECT_FALSE(test_api_
->touch_selection_controller());
2415 const int x
= GetCursorPositionX(2);
2417 // Tapping on the textfield should turn on the TouchSelectionController.
2418 ui::GestureEventDetails
tap_details(ui::ET_GESTURE_TAP
);
2419 tap_details
.set_tap_count(1);
2420 GestureEventForTest
tap(x
, 0, tap_details
);
2421 textfield_
->OnGestureEvent(&tap
);
2422 EXPECT_TRUE(test_api_
->touch_selection_controller());
2424 // Un-focusing the textfield should reset the TouchSelectionController
2425 textfield_
->GetFocusManager()->ClearFocus();
2426 EXPECT_FALSE(test_api_
->touch_selection_controller());
2427 textfield_
->RequestFocus();
2429 // With touch editing enabled, long press should not show context menu.
2430 // Instead, select word and invoke TouchSelectionController.
2431 GestureEventForTest
long_press_1(
2432 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2433 textfield_
->OnGestureEvent(&long_press_1
);
2434 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2435 EXPECT_TRUE(test_api_
->touch_selection_controller());
2436 EXPECT_TRUE(long_press_1
.handled());
2438 // With touch drag drop enabled, long pressing in the selected region should
2439 // start a drag and remove TouchSelectionController.
2440 ASSERT_TRUE(switches::IsTouchDragDropEnabled());
2441 GestureEventForTest
long_press_2(
2442 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2443 textfield_
->OnGestureEvent(&long_press_2
);
2444 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2445 EXPECT_FALSE(test_api_
->touch_selection_controller());
2446 EXPECT_FALSE(long_press_2
.handled());
2448 // After disabling touch drag drop, long pressing again in the selection
2449 // region should not do anything.
2450 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2451 switches::kDisableTouchDragDrop
);
2452 ASSERT_FALSE(switches::IsTouchDragDropEnabled());
2453 GestureEventForTest
long_press_3(
2454 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2455 textfield_
->OnGestureEvent(&long_press_3
);
2456 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2457 EXPECT_FALSE(test_api_
->touch_selection_controller());
2458 EXPECT_FALSE(long_press_3
.handled());
2462 TEST_F(TextfieldTouchSelectionTest
, TouchSelectionInUnfocusableTextfield
) {
2464 textfield_
->SetText(ASCIIToUTF16("hello world"));
2465 gfx::Point
touch_point(GetCursorPositionX(2), 0);
2467 // Disable textfield and tap on it. Touch text selection should not get
2469 textfield_
->SetEnabled(false);
2471 EXPECT_FALSE(test_api_
->touch_selection_controller());
2472 textfield_
->SetEnabled(true);
2474 // Make textfield unfocusable and tap on it. Touch text selection should not
2476 textfield_
->SetFocusable(false);
2478 EXPECT_FALSE(textfield_
->HasFocus());
2479 EXPECT_FALSE(test_api_
->touch_selection_controller());
2480 textfield_
->SetFocusable(true);
2483 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
2484 #if defined(OS_MACOSX) && !defined(USE_AURA)
2485 #define MAYBE_TapOnSelection DISABLED_TapOnSelection
2487 #define MAYBE_TapOnSelection TapOnSelection
2490 TEST_F(TextfieldTouchSelectionTest
, MAYBE_TapOnSelection
) {
2492 textfield_
->SetText(ASCIIToUTF16("hello world"));
2493 gfx::Range
sel_range(2, 7);
2494 gfx::Range
tap_range(5, 5);
2495 gfx::Rect tap_rect
=
2496 GetCursorBounds(gfx::SelectionModel(tap_range
, gfx::CURSOR_FORWARD
));
2497 gfx::Point tap_point
= tap_rect
.CenterPoint();
2499 // Select range |sel_range| and check if touch selection handles are not
2500 // present and correct range is selected.
2501 textfield_
->SetSelectionRange(sel_range
);
2503 textfield_
->GetSelectionRange(&range
);
2504 EXPECT_FALSE(test_api_
->touch_selection_controller());
2505 EXPECT_EQ(sel_range
, range
);
2507 // Tap on selection and check if touch selectoin handles are shown, but
2508 // selection range is not modified.
2510 textfield_
->GetSelectionRange(&range
);
2511 EXPECT_TRUE(test_api_
->touch_selection_controller());
2512 EXPECT_EQ(sel_range
, range
);
2514 // Tap again on selection and check if touch selection handles are still
2515 // present and selection is changed to a cursor at tap location.
2517 textfield_
->GetSelectionRange(&range
);
2518 EXPECT_TRUE(test_api_
->touch_selection_controller());
2519 EXPECT_EQ(tap_range
, range
);
2522 TEST_F(TextfieldTest
, AccessiblePasswordTest
) {
2524 textfield_
->SetText(ASCIIToUTF16("password"));
2526 ui::AXViewState state_regular
;
2527 textfield_
->GetAccessibleState(&state_regular
);
2528 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD
, state_regular
.role
);
2529 EXPECT_EQ(ASCIIToUTF16("password"), state_regular
.value
);
2530 EXPECT_FALSE(state_regular
.HasStateFlag(ui::AX_STATE_PROTECTED
));
2532 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
2533 ui::AXViewState state_protected
;
2534 textfield_
->GetAccessibleState(&state_protected
);
2535 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD
, state_protected
.role
);
2536 EXPECT_EQ(ASCIIToUTF16("********"), state_protected
.value
);
2537 EXPECT_TRUE(state_protected
.HasStateFlag(ui::AX_STATE_PROTECTED
));
2540 } // namespace views