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 #if defined(OS_MACOSX) && !defined(USE_AURA)
55 #include "ui/events/test/event_generator.h"
58 using base::ASCIIToUTF16
;
59 using base::UTF8ToUTF16
;
60 using base::WideToUTF16
;
62 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
66 const base::char16 kHebrewLetterSamekh
= 0x05E1;
68 class MockInputMethod
: public ui::InputMethodBase
{
71 ~MockInputMethod() override
;
73 // Overridden from InputMethod:
74 bool OnUntranslatedIMEMessage(const base::NativeEvent
& event
,
75 NativeEventResult
* result
) override
;
76 void DispatchKeyEvent(ui::KeyEvent
* key
) override
;
77 void OnTextInputTypeChanged(const ui::TextInputClient
* client
) override
;
78 void OnCaretBoundsChanged(const ui::TextInputClient
* client
) override
{}
79 void CancelComposition(const ui::TextInputClient
* client
) override
;
80 void OnInputLocaleChanged() override
{}
81 std::string
GetInputLocale() override
;
82 bool IsCandidatePopupOpen() const override
;
83 void ShowImeIfNeeded() override
{}
85 bool untranslated_ime_message_called() const {
86 return untranslated_ime_message_called_
;
88 bool text_input_type_changed() const { return text_input_type_changed_
; }
89 bool cancel_composition_called() const { return cancel_composition_called_
; }
91 // Clears all internal states and result.
94 void SetCompositionTextForNextKey(const ui::CompositionText
& composition
);
95 void SetResultTextForNextKey(const base::string16
& result
);
98 // Overridden from InputMethodBase.
99 void OnWillChangeFocusedClient(ui::TextInputClient
* focused_before
,
100 ui::TextInputClient
* focused
) override
;
102 // Clears boolean states defined below.
105 // Whether a mock composition or result is scheduled for the next key event.
106 bool HasComposition();
108 // Clears only composition information and result text.
109 void ClearComposition();
111 // Composition information for the next key event. It'll be cleared
112 // automatically after dispatching the next key event.
113 ui::CompositionText composition_
;
115 // Result text for the next key event. It'll be cleared automatically after
116 // dispatching the next key event.
117 base::string16 result_text_
;
119 // Record call state of corresponding methods. They will be set to false
120 // automatically before dispatching a key event.
121 bool untranslated_ime_message_called_
;
122 bool text_input_type_changed_
;
123 bool cancel_composition_called_
;
125 DISALLOW_COPY_AND_ASSIGN(MockInputMethod
);
128 MockInputMethod::MockInputMethod()
129 : untranslated_ime_message_called_(false),
130 text_input_type_changed_(false),
131 cancel_composition_called_(false) {
134 MockInputMethod::~MockInputMethod() {
137 bool MockInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent
& event
,
138 NativeEventResult
* result
) {
140 *result
= NativeEventResult();
144 void MockInputMethod::DispatchKeyEvent(ui::KeyEvent
* key
) {
145 // Checks whether the key event is from EventGenerator on Windows which will
146 // generate key event for WM_CHAR.
147 // The MockInputMethod will insert char on WM_KEYDOWN so ignore WM_CHAR here.
148 if (key
->is_char() && key
->HasNativeEvent())
151 bool handled
= !IsTextInputTypeNone() && HasComposition();
154 DCHECK(!key
->is_char());
155 ui::KeyEvent
mock_key(ui::ET_KEY_PRESSED
,
158 DispatchKeyEventPostIME(&mock_key
);
160 DispatchKeyEventPostIME(key
);
163 ui::TextInputClient
* client
= GetTextInputClient();
166 if (result_text_
.length())
167 client
->InsertText(result_text_
);
168 if (composition_
.text
.length())
169 client
->SetCompositionText(composition_
);
171 client
->ClearCompositionText();
172 } else if (key
->type() == ui::ET_KEY_PRESSED
) {
173 base::char16 ch
= key
->GetCharacter();
175 client
->InsertChar(ch
, key
->flags());
182 void MockInputMethod::OnTextInputTypeChanged(
183 const ui::TextInputClient
* client
) {
184 if (IsTextInputClientFocused(client
))
185 text_input_type_changed_
= true;
186 InputMethodBase::OnTextInputTypeChanged(client
);
189 void MockInputMethod::CancelComposition(const ui::TextInputClient
* client
) {
190 if (IsTextInputClientFocused(client
)) {
191 cancel_composition_called_
= true;
196 std::string
MockInputMethod::GetInputLocale() {
200 bool MockInputMethod::IsCandidatePopupOpen() const {
204 void MockInputMethod::OnWillChangeFocusedClient(
205 ui::TextInputClient
* focused_before
,
206 ui::TextInputClient
* focused
) {
207 ui::TextInputClient
* client
= GetTextInputClient();
208 if (client
&& client
->HasCompositionText())
209 client
->ConfirmCompositionText();
213 void MockInputMethod::Clear() {
218 void MockInputMethod::SetCompositionTextForNextKey(
219 const ui::CompositionText
& composition
) {
220 composition_
= composition
;
223 void MockInputMethod::SetResultTextForNextKey(const base::string16
& result
) {
224 result_text_
= result
;
227 void MockInputMethod::ClearStates() {
228 untranslated_ime_message_called_
= false;
229 text_input_type_changed_
= false;
230 cancel_composition_called_
= false;
233 bool MockInputMethod::HasComposition() {
234 return composition_
.text
.length() || result_text_
.length();
237 void MockInputMethod::ClearComposition() {
238 composition_
.Clear();
239 result_text_
.clear();
242 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
243 class TestTextfield
: public views::Textfield
{
248 key_received_(false),
249 weak_ptr_factory_(this) {}
251 bool OnKeyPressed(const ui::KeyEvent
& e
) override
{
252 key_received_
= true;
254 // Since OnKeyPressed() might destroy |this|, get a weak pointer and
255 // verify it isn't null before writing the bool value to key_handled_.
256 base::WeakPtr
<TestTextfield
> textfield(weak_ptr_factory_
.GetWeakPtr());
257 bool key
= views::Textfield::OnKeyPressed(e
);
267 bool OnKeyReleased(const ui::KeyEvent
& e
) override
{
268 key_received_
= true;
269 key_handled_
= views::Textfield::OnKeyReleased(e
);
270 EXPECT_FALSE(key_handled_
); // Textfield doesn't override OnKeyReleased.
274 // ui::TextInputClient overrides:
275 void InsertChar(base::char16 ch
, int flags
) override
{
276 views::Textfield::InsertChar(ch
, flags
);
277 #if defined(OS_MACOSX)
278 // On Mac, characters are inserted directly rather than attempting to get a
279 // unicode character from the ui::KeyEvent (which isn't always possible).
280 key_received_
= true;
284 bool key_handled() const { return key_handled_
; }
285 bool key_received() const { return key_received_
; }
287 void clear() { key_received_
= key_handled_
= false; }
293 base::WeakPtrFactory
<TestTextfield
> weak_ptr_factory_
;
295 DISALLOW_COPY_AND_ASSIGN(TestTextfield
);
298 // Convenience to make constructing a GestureEvent simpler.
299 class GestureEventForTest
: public ui::GestureEvent
{
301 GestureEventForTest(int x
, int y
, ui::GestureEventDetails details
)
302 : GestureEvent(x
, y
, 0, base::TimeDelta(), details
) {}
305 DISALLOW_COPY_AND_ASSIGN(GestureEventForTest
);
308 // This controller will happily destroy the target textfield passed on
309 // construction when a key event is triggered.
310 class TextfieldDestroyerController
: public views::TextfieldController
{
312 explicit TextfieldDestroyerController(views::Textfield
* target
)
314 target_
->set_controller(this);
317 views::Textfield
* target() { return target_
.get(); }
319 // views::TextfieldController:
320 bool HandleKeyEvent(views::Textfield
* sender
,
321 const ui::KeyEvent
& key_event
) override
{
328 scoped_ptr
<views::Textfield
> target_
;
331 base::string16
GetClipboardText(ui::ClipboardType type
) {
333 ui::Clipboard::GetForCurrentThread()->ReadText(type
, &text
);
337 void SetClipboardText(ui::ClipboardType type
, const std::string
& text
) {
338 ui::ScopedClipboardWriter(type
).WriteText(ASCIIToUTF16(text
));
345 class TextfieldTest
: public ViewsTestBase
, public TextfieldController
{
352 on_before_user_action_(0),
353 on_after_user_action_(0),
354 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST
) {
355 input_method_
= new MockInputMethod();
356 ui::SetUpInputMethodForTesting(input_method_
);
360 void TearDown() override
{
363 ViewsTestBase::TearDown();
366 ui::ClipboardType
GetAndResetCopiedToClipboard() {
367 ui::ClipboardType clipboard_type
= copied_to_clipboard_
;
368 copied_to_clipboard_
= ui::CLIPBOARD_TYPE_LAST
;
369 return clipboard_type
;
372 // TextfieldController:
373 void ContentsChanged(Textfield
* sender
,
374 const base::string16
& new_contents
) override
{
375 // Paste calls TextfieldController::ContentsChanged() explicitly even if the
376 // paste action did not change the content. So |new_contents| may match
377 // |last_contents_|. For more info, see http://crbug.com/79002
378 last_contents_
= new_contents
;
381 void OnBeforeUserAction(Textfield
* sender
) override
{
382 ++on_before_user_action_
;
385 void OnAfterUserAction(Textfield
* sender
) override
{
386 ++on_after_user_action_
;
389 void OnAfterCutOrCopy(ui::ClipboardType clipboard_type
) override
{
390 copied_to_clipboard_
= clipboard_type
;
393 void InitTextfield() {
397 void InitTextfields(int count
) {
398 ASSERT_FALSE(textfield_
);
399 textfield_
= new TestTextfield();
400 textfield_
->set_controller(this);
401 widget_
= new Widget();
403 // The widget type must be an activatable type, and we don't want to worry
404 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS.
405 Widget::InitParams params
=
406 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
408 params
.bounds
= gfx::Rect(100, 100, 100, 100);
409 widget_
->Init(params
);
410 input_method_
->SetDelegate(
411 test::WidgetTest::GetInputMethodDelegateForWidget(widget_
));
412 View
* container
= new View();
413 widget_
->SetContentsView(container
);
414 container
->AddChildView(textfield_
);
415 textfield_
->SetBoundsRect(params
.bounds
);
416 textfield_
->set_id(1);
417 test_api_
.reset(new TextfieldTestApi(textfield_
));
419 for (int i
= 1; i
< count
; i
++) {
420 Textfield
* textfield
= new Textfield();
421 container
->AddChildView(textfield
);
422 textfield
->set_id(i
+ 1);
425 model_
= test_api_
->model();
426 model_
->ClearEditHistory();
428 // Since the window type is activatable, showing the widget will also
429 // activate it. Calling Activate directly is insufficient, since that does
430 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the
431 // widget and the textfield must have focus to properly handle input.
433 textfield_
->RequestFocus();
435 // On Mac, activation is asynchronous since desktop widgets are used. We
436 // don't want parallel tests to steal active status either, so fake it.
437 #if defined(OS_MACOSX) && !defined(USE_AURA)
438 fake_activation_
= test::WidgetTest::FakeWidgetIsActiveAlways();
440 // This is only used on Mac. See comment regarding |event_generator_| below.
441 event_generator_
.reset(
442 new ui::test::EventGenerator(GetContext(), widget_
->GetNativeWindow()));
446 ui::MenuModel
* GetContextMenuModel() {
447 test_api_
->UpdateContextMenu();
448 return test_api_
->context_menu_contents();
451 // True if native Mac keystrokes should be used (to avoid ifdef litter).
452 bool TestingNativeMac() {
453 #if defined(OS_MACOSX)
461 void SendKeyEvent(ui::KeyboardCode key_code
,
464 bool control_or_command
,
466 bool control
= control_or_command
;
467 bool command
= false;
469 // By default, swap control and command for native events on Mac. This
470 // handles most cases.
471 if (TestingNativeMac())
472 std::swap(control
, command
);
474 int flags
= (alt
? ui::EF_ALT_DOWN
: 0) | (shift
? ui::EF_SHIFT_DOWN
: 0) |
475 (control
? ui::EF_CONTROL_DOWN
: 0) |
476 (command
? ui::EF_COMMAND_DOWN
: 0) |
477 (caps_lock
? ui::EF_CAPS_LOCK_DOWN
: 0);
479 #if defined(OS_MACOSX) && !defined(USE_AURA)
480 // The Mac EventGenerator hooks in before IME. It sends events first to an
481 // NSResponder, which is necessary to interpret keyboard events into
482 // appropriate editing commands.
483 event_generator_
->PressKey(key_code
, flags
);
485 // TODO(shuchen): making EventGenerator support input method and using
486 // EventGenerator here. crbug.com/512315.
487 ui::KeyEvent
event(ui::ET_KEY_PRESSED
, key_code
, flags
);
488 input_method_
->DispatchKeyEvent(&event
);
492 void SendKeyEvent(ui::KeyboardCode key_code
,
494 bool control_or_command
) {
495 SendKeyEvent(key_code
, false, shift
, control_or_command
, false);
498 void SendKeyEvent(ui::KeyboardCode key_code
) {
499 SendKeyEvent(key_code
, false, false);
502 void SendKeyEvent(base::char16 ch
) {
504 ui::KeyboardCode code
=
505 ch
== ' ' ? ui::VKEY_SPACE
:
506 static_cast<ui::KeyboardCode
>(ui::VKEY_A
+ ch
- 'a');
509 // For unicode characters, assume they come from IME rather than the
510 // keyboard. So they are dispatched directly to the input method.
511 ui::KeyEvent
event(ch
, ui::VKEY_UNKNOWN
, ui::EF_NONE
);
512 input_method_
->DispatchKeyEvent(&event
);
516 // Sends a platform-specific move (and select) to start of line.
517 void SendHomeEvent(bool shift
) {
518 if (TestingNativeMac()) {
519 // Use Cmd+Left on native Mac. An RTL-agnostic "end" doesn't have a
520 // default key-binding on Mac.
521 SendKeyEvent(ui::VKEY_LEFT
, shift
/* shift */, true /* command */);
524 SendKeyEvent(ui::VKEY_HOME
, shift
/* shift */, false /* control */);
527 // Sends a platform-specific move (and select) to end of line.
528 void SendEndEvent(bool shift
) {
529 if (TestingNativeMac()) {
530 SendKeyEvent(ui::VKEY_RIGHT
, shift
, true); // Cmd+Right.
533 SendKeyEvent(ui::VKEY_END
, shift
, false);
536 // Sends {delete, move, select} word {forward, backward}.
537 void SendWordEvent(ui::KeyboardCode key
, bool shift
) {
541 if (TestingNativeMac()) {
542 // Use Alt+Left/Right/Backspace on native Mac.
546 SendKeyEvent(key
, alt
, shift
, control
, caps
);
549 // Sends Shift+Delete if supported, otherwise Cmd+X again.
550 void SendAlternateCut() {
551 if (TestingNativeMac())
552 SendKeyEvent(ui::VKEY_X
, false, true);
554 SendKeyEvent(ui::VKEY_DELETE
, true, false);
557 // Sends Ctrl+Insert if supported, otherwise Cmd+C again.
558 void SendAlternateCopy() {
559 if (TestingNativeMac())
560 SendKeyEvent(ui::VKEY_C
, false, true);
562 SendKeyEvent(ui::VKEY_INSERT
, false, true);
565 // Sends Shift+Insert if supported, otherwise Cmd+V again.
566 void SendAlternatePaste() {
567 if (TestingNativeMac())
568 SendKeyEvent(ui::VKEY_V
, false, true);
570 SendKeyEvent(ui::VKEY_INSERT
, true, false);
573 View
* GetFocusedView() {
574 return widget_
->GetFocusManager()->GetFocusedView();
577 int GetCursorPositionX(int cursor_pos
) {
578 return test_api_
->GetRenderText()->GetCursorBounds(
579 gfx::SelectionModel(cursor_pos
, gfx::CURSOR_FORWARD
), false).x();
582 // Get the current cursor bounds.
583 gfx::Rect
GetCursorBounds() {
584 return test_api_
->GetRenderText()->GetUpdatedCursorBounds();
587 // Get the cursor bounds of |sel|.
588 gfx::Rect
GetCursorBounds(const gfx::SelectionModel
& sel
) {
589 return test_api_
->GetRenderText()->GetCursorBounds(sel
, true);
592 gfx::Rect
GetDisplayRect() {
593 return test_api_
->GetRenderText()->display_rect();
596 // Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and
597 // y-axis is in the middle of |bound|'s vertical range.
598 void MouseClick(const gfx::Rect bound
, int x_offset
) {
599 gfx::Point
point(bound
.x() + x_offset
, bound
.y() + bound
.height() / 2);
600 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, point
, point
,
601 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
602 ui::EF_LEFT_MOUSE_BUTTON
);
603 textfield_
->OnMousePressed(click
);
604 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, point
, point
,
605 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
606 ui::EF_LEFT_MOUSE_BUTTON
);
607 textfield_
->OnMouseReleased(release
);
610 // This is to avoid double/triple click.
611 void NonClientMouseClick() {
612 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
613 ui::EventTimeForNow(),
614 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_NON_CLIENT
,
615 ui::EF_LEFT_MOUSE_BUTTON
);
616 textfield_
->OnMousePressed(click
);
617 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, gfx::Point(), gfx::Point(),
618 ui::EventTimeForNow(),
619 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_NON_CLIENT
,
620 ui::EF_LEFT_MOUSE_BUTTON
);
621 textfield_
->OnMouseReleased(release
);
624 void VerifyTextfieldContextMenuContents(bool textfield_has_selection
,
626 ui::MenuModel
* menu
) {
627 EXPECT_EQ(can_undo
, menu
->IsEnabledAt(0 /* UNDO */));
628 EXPECT_TRUE(menu
->IsEnabledAt(1 /* Separator */));
629 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(2 /* CUT */));
630 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(3 /* COPY */));
631 EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
).empty(),
632 menu
->IsEnabledAt(4 /* PASTE */));
633 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(5 /* DELETE */));
634 EXPECT_TRUE(menu
->IsEnabledAt(6 /* Separator */));
635 EXPECT_TRUE(menu
->IsEnabledAt(7 /* SELECT ALL */));
638 // We need widget to populate wrapper class.
641 TestTextfield
* textfield_
;
642 scoped_ptr
<TextfieldTestApi
> test_api_
;
643 TextfieldModel
* model_
;
645 // The string from Controller::ContentsChanged callback.
646 base::string16 last_contents_
;
648 // For testing input method related behaviors.
649 MockInputMethod
* input_method_
;
651 // Indicates how many times OnBeforeUserAction() is called.
652 int on_before_user_action_
;
654 // Indicates how many times OnAfterUserAction() is called.
655 int on_after_user_action_
;
658 ui::ClipboardType copied_to_clipboard_
;
659 scoped_ptr
<test::WidgetTest::FakeActivation
> fake_activation_
;
661 #if defined(OS_MACOSX) && !defined(USE_AURA)
662 scoped_ptr
<ui::test::EventGenerator
> event_generator_
;
665 DISALLOW_COPY_AND_ASSIGN(TextfieldTest
);
668 TEST_F(TextfieldTest
, ModelChangesTest
) {
671 // TextfieldController::ContentsChanged() shouldn't be called when changing
672 // text programmatically.
673 last_contents_
.clear();
674 textfield_
->SetText(ASCIIToUTF16("this is"));
676 EXPECT_STR_EQ("this is", model_
->text());
677 EXPECT_STR_EQ("this is", textfield_
->text());
678 EXPECT_TRUE(last_contents_
.empty());
680 textfield_
->AppendText(ASCIIToUTF16(" a test"));
681 EXPECT_STR_EQ("this is a test", model_
->text());
682 EXPECT_STR_EQ("this is a test", textfield_
->text());
683 EXPECT_TRUE(last_contents_
.empty());
685 EXPECT_EQ(base::string16(), textfield_
->GetSelectedText());
686 textfield_
->SelectAll(false);
687 EXPECT_STR_EQ("this is a test", textfield_
->GetSelectedText());
688 EXPECT_TRUE(last_contents_
.empty());
691 TEST_F(TextfieldTest
, KeyTest
) {
693 // Event flags: key, alt, shift, ctrl, caps-lock.
694 SendKeyEvent(ui::VKEY_T
, false, true, false, false);
695 SendKeyEvent(ui::VKEY_E
, false, false, false, false);
696 SendKeyEvent(ui::VKEY_X
, false, true, false, true);
697 SendKeyEvent(ui::VKEY_T
, false, false, false, true);
698 SendKeyEvent(ui::VKEY_1
, false, true, false, false);
699 SendKeyEvent(ui::VKEY_1
, false, false, false, false);
700 SendKeyEvent(ui::VKEY_1
, false, true, false, true);
701 SendKeyEvent(ui::VKEY_1
, false, false, false, true);
703 // On Mac, Caps+Shift remains uppercase.
704 if (TestingNativeMac())
705 EXPECT_STR_EQ("TeXT!1!1", textfield_
->text());
707 EXPECT_STR_EQ("TexT!1!1", textfield_
->text());
710 TEST_F(TextfieldTest
, ControlAndSelectTest
) {
711 // Insert a test string in a textfield.
713 textfield_
->SetText(ASCIIToUTF16("one two three"));
714 SendHomeEvent(false);
715 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
716 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
717 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
719 EXPECT_STR_EQ("one", textfield_
->GetSelectedText());
722 SendWordEvent(ui::VKEY_RIGHT
, true);
723 EXPECT_STR_EQ("one two", textfield_
->GetSelectedText());
724 SendWordEvent(ui::VKEY_RIGHT
, true);
725 EXPECT_STR_EQ("one two three", textfield_
->GetSelectedText());
726 SendWordEvent(ui::VKEY_LEFT
, true);
727 EXPECT_STR_EQ("one two ", textfield_
->GetSelectedText());
728 SendWordEvent(ui::VKEY_LEFT
, true);
729 EXPECT_STR_EQ("one ", textfield_
->GetSelectedText());
731 // Replace the selected text.
732 SendKeyEvent(ui::VKEY_Z
, true, false);
733 SendKeyEvent(ui::VKEY_E
, true, false);
734 SendKeyEvent(ui::VKEY_R
, true, false);
735 SendKeyEvent(ui::VKEY_O
, true, false);
736 SendKeyEvent(ui::VKEY_SPACE
, false, false);
737 EXPECT_STR_EQ("ZERO two three", textfield_
->text());
740 EXPECT_STR_EQ("two three", textfield_
->GetSelectedText());
742 EXPECT_STR_EQ("ZERO ", textfield_
->GetSelectedText());
745 TEST_F(TextfieldTest
, InsertionDeletionTest
) {
746 // Insert a test string in a textfield.
748 for (size_t i
= 0; i
< 10; i
++)
749 SendKeyEvent(static_cast<ui::KeyboardCode
>(ui::VKEY_A
+ i
));
750 EXPECT_STR_EQ("abcdefghij", textfield_
->text());
752 // Test the delete and backspace keys.
753 textfield_
->SelectRange(gfx::Range(5));
754 for (int i
= 0; i
< 3; i
++)
755 SendKeyEvent(ui::VKEY_BACK
);
756 EXPECT_STR_EQ("abfghij", textfield_
->text());
757 for (int i
= 0; i
< 3; i
++)
758 SendKeyEvent(ui::VKEY_DELETE
);
759 EXPECT_STR_EQ("abij", textfield_
->text());
761 // Select all and replace with "k".
762 textfield_
->SelectAll(false);
763 SendKeyEvent(ui::VKEY_K
);
764 EXPECT_STR_EQ("k", textfield_
->text());
766 // Delete the previous word from cursor.
768 textfield_
->SetText(ASCIIToUTF16("one two three four"));
770 SendWordEvent(ui::VKEY_BACK
, shift
);
771 EXPECT_STR_EQ("one two three ", textfield_
->text());
773 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
775 SendWordEvent(ui::VKEY_LEFT
, shift
);
777 SendWordEvent(ui::VKEY_BACK
, shift
);
778 #if defined(OS_LINUX)
779 EXPECT_STR_EQ("three ", textfield_
->text());
781 EXPECT_STR_EQ("one three ", textfield_
->text());
784 // Delete the next word from cursor.
785 textfield_
->SetText(ASCIIToUTF16("one two three four"));
787 SendHomeEvent(shift
);
788 SendWordEvent(ui::VKEY_DELETE
, shift
);
789 EXPECT_STR_EQ(" two three four", textfield_
->text());
791 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
793 SendWordEvent(ui::VKEY_RIGHT
, shift
);
795 SendWordEvent(ui::VKEY_DELETE
, shift
);
796 #if defined(OS_LINUX)
797 EXPECT_STR_EQ(" two", textfield_
->text());
799 EXPECT_STR_EQ(" two four", textfield_
->text());
803 TEST_F(TextfieldTest
, PasswordTest
) {
805 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
806 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
807 EXPECT_TRUE(textfield_
->enabled());
808 EXPECT_TRUE(textfield_
->IsFocusable());
810 last_contents_
.clear();
811 textfield_
->SetText(ASCIIToUTF16("password"));
812 // Ensure text() and the callback returns the actual text instead of "*".
813 EXPECT_STR_EQ("password", textfield_
->text());
814 EXPECT_TRUE(last_contents_
.empty());
815 model_
->SelectAll(false);
816 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "foo");
818 // Cut and copy should be disabled.
819 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
820 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
821 SendKeyEvent(ui::VKEY_X
, false, true);
822 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
823 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
824 SendKeyEvent(ui::VKEY_C
, false, true);
826 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
827 EXPECT_STR_EQ("password", textfield_
->text());
828 // [Shift]+[Delete] should just delete without copying text to the clipboard.
829 textfield_
->SelectAll(false);
830 SendKeyEvent(ui::VKEY_DELETE
, true, false);
832 // Paste should work normally.
833 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
834 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
835 SendKeyEvent(ui::VKEY_V
, false, true);
836 SendAlternatePaste();
837 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
838 EXPECT_STR_EQ("foofoofoo", textfield_
->text());
841 TEST_F(TextfieldTest
, TextInputType
) {
845 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT
, textfield_
->GetTextInputType());
848 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_URL
);
849 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL
, textfield_
->GetTextInputType());
850 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
851 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
853 // Readonly textfields have type NONE
854 textfield_
->SetReadOnly(true);
855 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, textfield_
->GetTextInputType());
857 textfield_
->SetReadOnly(false);
858 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
860 // As do disabled textfields
861 textfield_
->SetEnabled(false);
862 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, textfield_
->GetTextInputType());
864 textfield_
->SetEnabled(true);
865 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
868 TEST_F(TextfieldTest
, OnKeyPress
) {
871 // Character keys are handled by the input method.
872 SendKeyEvent(ui::VKEY_A
);
873 EXPECT_TRUE(textfield_
->key_received());
874 EXPECT_FALSE(textfield_
->key_handled());
877 // Arrow keys and home/end are handled by the textfield.
878 SendKeyEvent(ui::VKEY_LEFT
);
879 EXPECT_TRUE(textfield_
->key_received());
880 EXPECT_TRUE(textfield_
->key_handled());
883 SendKeyEvent(ui::VKEY_RIGHT
);
884 EXPECT_TRUE(textfield_
->key_received());
885 EXPECT_TRUE(textfield_
->key_handled());
888 const bool shift
= false;
889 SendHomeEvent(shift
);
890 EXPECT_TRUE(textfield_
->key_received());
891 EXPECT_TRUE(textfield_
->key_handled());
895 EXPECT_TRUE(textfield_
->key_received());
896 EXPECT_TRUE(textfield_
->key_handled());
899 // F20, up/down key won't be handled.
900 SendKeyEvent(ui::VKEY_F20
);
901 #if defined(OS_MACOSX)
902 // On Mac, key combinations that don't map to editing commands are forwarded
903 // on to the next responder, usually ending up at the window, which will beep.
904 EXPECT_FALSE(textfield_
->key_received());
906 EXPECT_TRUE(textfield_
->key_received());
908 EXPECT_FALSE(textfield_
->key_handled());
911 SendKeyEvent(ui::VKEY_UP
);
912 EXPECT_TRUE(textfield_
->key_received());
913 EXPECT_FALSE(textfield_
->key_handled());
916 SendKeyEvent(ui::VKEY_DOWN
);
917 EXPECT_TRUE(textfield_
->key_received());
918 EXPECT_FALSE(textfield_
->key_handled());
922 // Tests that default key bindings are handled even with a delegate installed.
923 TEST_F(TextfieldTest
, OnKeyPressBinding
) {
926 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
927 // Install a TextEditKeyBindingsDelegateAuraLinux that does nothing.
928 class TestDelegate
: public ui::TextEditKeyBindingsDelegateAuraLinux
{
931 ~TestDelegate() override
{}
934 const ui::Event
& event
,
935 std::vector
<ui::TextEditCommandAuraLinux
>* commands
) override
{
940 DISALLOW_COPY_AND_ASSIGN(TestDelegate
);
943 TestDelegate delegate
;
944 ui::SetTextEditKeyBindingsDelegate(&delegate
);
947 SendKeyEvent(ui::VKEY_A
, false, false);
948 EXPECT_STR_EQ("a", textfield_
->text());
951 // Undo/Redo command keys are handled by the textfield.
952 SendKeyEvent(ui::VKEY_Z
, false, true);
953 EXPECT_TRUE(textfield_
->key_received());
954 EXPECT_TRUE(textfield_
->key_handled());
955 EXPECT_TRUE(textfield_
->text().empty());
958 SendKeyEvent(ui::VKEY_Z
, true, true);
959 EXPECT_TRUE(textfield_
->key_received());
960 EXPECT_TRUE(textfield_
->key_handled());
961 EXPECT_STR_EQ("a", textfield_
->text());
964 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
965 ui::SetTextEditKeyBindingsDelegate(NULL
);
969 TEST_F(TextfieldTest
, CursorMovement
) {
972 // Test with trailing whitespace.
973 textfield_
->SetText(ASCIIToUTF16("one two hre "));
975 // Send the cursor at the end.
976 SendKeyEvent(ui::VKEY_END
);
978 // Ctrl+Left should move the cursor just before the last word.
979 const bool shift
= false;
980 SendWordEvent(ui::VKEY_LEFT
, shift
);
981 SendKeyEvent(ui::VKEY_T
);
982 EXPECT_STR_EQ("one two thre ", textfield_
->text());
983 EXPECT_STR_EQ("one two thre ", last_contents_
);
985 // Ctrl+Right should move the cursor to the end of the last word.
986 SendWordEvent(ui::VKEY_RIGHT
, shift
);
987 SendKeyEvent(ui::VKEY_E
);
988 EXPECT_STR_EQ("one two three ", textfield_
->text());
989 EXPECT_STR_EQ("one two three ", last_contents_
);
991 // Ctrl+Right again should move the cursor to the end.
992 SendWordEvent(ui::VKEY_RIGHT
, shift
);
993 SendKeyEvent(ui::VKEY_BACK
);
994 EXPECT_STR_EQ("one two three", textfield_
->text());
995 EXPECT_STR_EQ("one two three", last_contents_
);
997 // Test with leading whitespace.
998 textfield_
->SetText(ASCIIToUTF16(" ne two"));
1000 // Send the cursor at the beginning.
1001 SendHomeEvent(shift
);
1003 // Ctrl+Right, then Ctrl+Left should move the cursor to the beginning of the
1005 SendWordEvent(ui::VKEY_RIGHT
, shift
);
1006 SendWordEvent(ui::VKEY_LEFT
, shift
);
1007 SendKeyEvent(ui::VKEY_O
);
1008 EXPECT_STR_EQ(" one two", textfield_
->text());
1009 EXPECT_STR_EQ(" one two", last_contents_
);
1011 // Ctrl+Left to move the cursor to the beginning of the first word.
1012 SendWordEvent(ui::VKEY_LEFT
, shift
);
1013 // Ctrl+Left again should move the cursor back to the very beginning.
1014 SendWordEvent(ui::VKEY_LEFT
, shift
);
1015 SendKeyEvent(ui::VKEY_DELETE
);
1016 EXPECT_STR_EQ("one two", textfield_
->text());
1017 EXPECT_STR_EQ("one two", last_contents_
);
1020 TEST_F(TextfieldTest
, FocusTraversalTest
) {
1022 textfield_
->RequestFocus();
1024 EXPECT_EQ(1, GetFocusedView()->id());
1025 widget_
->GetFocusManager()->AdvanceFocus(false);
1026 EXPECT_EQ(2, GetFocusedView()->id());
1027 widget_
->GetFocusManager()->AdvanceFocus(false);
1028 EXPECT_EQ(3, GetFocusedView()->id());
1029 // Cycle back to the first textfield.
1030 widget_
->GetFocusManager()->AdvanceFocus(false);
1031 EXPECT_EQ(1, GetFocusedView()->id());
1033 widget_
->GetFocusManager()->AdvanceFocus(true);
1034 EXPECT_EQ(3, GetFocusedView()->id());
1035 widget_
->GetFocusManager()->AdvanceFocus(true);
1036 EXPECT_EQ(2, GetFocusedView()->id());
1037 widget_
->GetFocusManager()->AdvanceFocus(true);
1038 EXPECT_EQ(1, GetFocusedView()->id());
1039 // Cycle back to the last textfield.
1040 widget_
->GetFocusManager()->AdvanceFocus(true);
1041 EXPECT_EQ(3, GetFocusedView()->id());
1043 // Request focus should still work.
1044 textfield_
->RequestFocus();
1045 EXPECT_EQ(1, GetFocusedView()->id());
1047 // Test if clicking on textfield view sets the focus.
1048 widget_
->GetFocusManager()->AdvanceFocus(true);
1049 EXPECT_EQ(3, GetFocusedView()->id());
1050 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
1051 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1052 ui::EF_LEFT_MOUSE_BUTTON
);
1053 textfield_
->OnMousePressed(click
);
1054 EXPECT_EQ(1, GetFocusedView()->id());
1056 // Tab/Shift+Tab should also cycle focus, not insert a tab character.
1057 SendKeyEvent(ui::VKEY_TAB
, false, false);
1058 EXPECT_EQ(2, GetFocusedView()->id());
1059 SendKeyEvent(ui::VKEY_TAB
, false, false);
1060 EXPECT_EQ(3, GetFocusedView()->id());
1061 // Cycle back to the first textfield.
1062 SendKeyEvent(ui::VKEY_TAB
, false, false);
1063 EXPECT_EQ(1, GetFocusedView()->id());
1065 SendKeyEvent(ui::VKEY_TAB
, true, false);
1066 EXPECT_EQ(3, GetFocusedView()->id());
1067 SendKeyEvent(ui::VKEY_TAB
, true, false);
1068 EXPECT_EQ(2, GetFocusedView()->id());
1069 SendKeyEvent(ui::VKEY_TAB
, true, false);
1070 EXPECT_EQ(1, GetFocusedView()->id());
1071 // Cycle back to the last textfield.
1072 SendKeyEvent(ui::VKEY_TAB
, true, false);
1073 EXPECT_EQ(3, GetFocusedView()->id());
1076 TEST_F(TextfieldTest
, ContextMenuDisplayTest
) {
1078 EXPECT_TRUE(textfield_
->context_menu_controller());
1079 textfield_
->SetText(ASCIIToUTF16("hello world"));
1080 ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE
);
1081 textfield_
->ClearEditHistory();
1082 EXPECT_TRUE(GetContextMenuModel());
1083 VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
1085 textfield_
->SelectAll(false);
1086 VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel());
1088 SendKeyEvent(ui::VKEY_T
);
1089 VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel());
1091 textfield_
->SelectAll(false);
1092 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1094 // Exercise the "paste enabled?" check in the verifier.
1095 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1096 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1099 TEST_F(TextfieldTest
, DoubleAndTripleClickTest
) {
1101 textfield_
->SetText(ASCIIToUTF16("hello world"));
1102 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
1103 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1104 ui::EF_LEFT_MOUSE_BUTTON
);
1105 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, gfx::Point(), gfx::Point(),
1106 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1107 ui::EF_LEFT_MOUSE_BUTTON
);
1108 ui::MouseEvent
double_click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
1109 ui::EventTimeForNow(),
1110 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_DOUBLE_CLICK
,
1111 ui::EF_LEFT_MOUSE_BUTTON
);
1113 // Test for double click.
1114 textfield_
->OnMousePressed(click
);
1115 textfield_
->OnMouseReleased(release
);
1116 EXPECT_TRUE(textfield_
->GetSelectedText().empty());
1117 textfield_
->OnMousePressed(double_click
);
1118 textfield_
->OnMouseReleased(release
);
1119 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
1121 // Test for triple click.
1122 textfield_
->OnMousePressed(click
);
1123 textfield_
->OnMouseReleased(release
);
1124 EXPECT_STR_EQ("hello world", textfield_
->GetSelectedText());
1126 // Another click should reset back to double click.
1127 textfield_
->OnMousePressed(click
);
1128 textfield_
->OnMouseReleased(release
);
1129 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
1132 TEST_F(TextfieldTest
, DragToSelect
) {
1134 textfield_
->SetText(ASCIIToUTF16("hello world"));
1135 const int kStart
= GetCursorPositionX(5);
1136 const int kEnd
= 500;
1137 gfx::Point
start_point(kStart
, 0);
1138 gfx::Point
end_point(kEnd
, 0);
1139 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, start_point
, start_point
,
1140 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1141 ui::EF_LEFT_MOUSE_BUTTON
);
1142 ui::MouseEvent
click_b(ui::ET_MOUSE_PRESSED
, end_point
, end_point
,
1143 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1144 ui::EF_LEFT_MOUSE_BUTTON
);
1145 ui::MouseEvent
drag_left(ui::ET_MOUSE_DRAGGED
, gfx::Point(), gfx::Point(),
1146 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1147 ui::MouseEvent
drag_right(ui::ET_MOUSE_DRAGGED
, end_point
, end_point
,
1148 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1149 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, end_point
, end_point
,
1150 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1151 ui::EF_LEFT_MOUSE_BUTTON
);
1152 textfield_
->OnMousePressed(click_a
);
1153 EXPECT_TRUE(textfield_
->GetSelectedText().empty());
1154 // Check that dragging left selects the beginning of the string.
1155 textfield_
->OnMouseDragged(drag_left
);
1156 base::string16 text_left
= textfield_
->GetSelectedText();
1157 EXPECT_STR_EQ("hello", text_left
);
1158 // Check that dragging right selects the rest of the string.
1159 textfield_
->OnMouseDragged(drag_right
);
1160 base::string16 text_right
= textfield_
->GetSelectedText();
1161 EXPECT_STR_EQ(" world", text_right
);
1162 // Check that releasing in the same location does not alter the selection.
1163 textfield_
->OnMouseReleased(release
);
1164 EXPECT_EQ(text_right
, textfield_
->GetSelectedText());
1165 // Check that dragging from beyond the text length works too.
1166 textfield_
->OnMousePressed(click_b
);
1167 textfield_
->OnMouseDragged(drag_left
);
1168 textfield_
->OnMouseReleased(release
);
1169 EXPECT_EQ(textfield_
->text(), textfield_
->GetSelectedText());
1173 TEST_F(TextfieldTest
, DragAndDrop_AcceptDrop
) {
1175 textfield_
->SetText(ASCIIToUTF16("hello world"));
1177 ui::OSExchangeData data
;
1178 base::string16
string(ASCIIToUTF16("string "));
1179 data
.SetString(string
);
1181 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1183 // Ensure that disabled textfields do not accept drops.
1184 textfield_
->SetEnabled(false);
1185 EXPECT_FALSE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1186 EXPECT_EQ(0, formats
);
1187 EXPECT_TRUE(custom_formats
.empty());
1188 EXPECT_FALSE(textfield_
->CanDrop(data
));
1189 textfield_
->SetEnabled(true);
1191 // Ensure that read-only textfields do not accept drops.
1192 textfield_
->SetReadOnly(true);
1193 EXPECT_FALSE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1194 EXPECT_EQ(0, formats
);
1195 EXPECT_TRUE(custom_formats
.empty());
1196 EXPECT_FALSE(textfield_
->CanDrop(data
));
1197 textfield_
->SetReadOnly(false);
1199 // Ensure that enabled and editable textfields do accept drops.
1200 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1201 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1202 EXPECT_TRUE(custom_formats
.empty());
1203 EXPECT_TRUE(textfield_
->CanDrop(data
));
1204 gfx::Point
drop_point(GetCursorPositionX(6), 0);
1205 ui::DropTargetEvent
drop(data
, drop_point
, drop_point
,
1206 ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_MOVE
);
1207 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_MOVE
,
1208 textfield_
->OnDragUpdated(drop
));
1209 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
, textfield_
->OnPerformDrop(drop
));
1210 EXPECT_STR_EQ("hello string world", textfield_
->text());
1212 // Ensure that textfields do not accept non-OSExchangeData::STRING types.
1213 ui::OSExchangeData bad_data
;
1214 bad_data
.SetFilename(base::FilePath(FILE_PATH_LITERAL("x")));
1215 ui::OSExchangeData::CustomFormat fmt
= ui::Clipboard::GetBitmapFormatType();
1216 bad_data
.SetPickledData(fmt
, base::Pickle());
1217 bad_data
.SetFileContents(base::FilePath(L
"x"), "x");
1218 bad_data
.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org"));
1219 ui::OSExchangeData::DownloadFileInfo
download(base::FilePath(), NULL
);
1220 bad_data
.SetDownloadFileInfo(download
);
1221 EXPECT_FALSE(textfield_
->CanDrop(bad_data
));
1225 TEST_F(TextfieldTest
, DragAndDrop_InitiateDrag
) {
1227 textfield_
->SetText(ASCIIToUTF16("hello string world"));
1229 // Ensure the textfield will provide selected text for drag data.
1230 base::string16 string
;
1231 ui::OSExchangeData data
;
1232 const gfx::Range
kStringRange(6, 12);
1233 textfield_
->SelectRange(kStringRange
);
1234 const gfx::Point
kStringPoint(GetCursorPositionX(9), 0);
1235 textfield_
->WriteDragDataForView(NULL
, kStringPoint
, &data
);
1236 EXPECT_TRUE(data
.GetString(&string
));
1237 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1239 // Ensure that disabled textfields do not support drag operations.
1240 textfield_
->SetEnabled(false);
1241 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1242 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1243 textfield_
->SetEnabled(true);
1244 // Ensure that textfields without selections do not support drag operations.
1245 textfield_
->ClearSelection();
1246 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1247 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1248 textfield_
->SelectRange(kStringRange
);
1249 // Ensure that password textfields do not support drag operations.
1250 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
1251 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1252 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1253 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT
);
1254 // Ensure that textfields only initiate drag operations inside the selection.
1255 ui::MouseEvent
press_event(ui::ET_MOUSE_PRESSED
, kStringPoint
, kStringPoint
,
1256 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1257 ui::EF_LEFT_MOUSE_BUTTON
);
1258 textfield_
->OnMousePressed(press_event
);
1259 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1260 textfield_
->GetDragOperationsForView(NULL
, gfx::Point()));
1261 EXPECT_FALSE(textfield_
->CanStartDragForView(NULL
, gfx::Point(),
1263 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
,
1264 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1265 EXPECT_TRUE(textfield_
->CanStartDragForView(NULL
, kStringPoint
,
1267 // Ensure that textfields support local moves.
1268 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1269 textfield_
->GetDragOperationsForView(textfield_
, kStringPoint
));
1272 TEST_F(TextfieldTest
, DragAndDrop_ToTheRight
) {
1274 textfield_
->SetText(ASCIIToUTF16("hello world"));
1276 base::string16 string
;
1277 ui::OSExchangeData data
;
1280 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1282 // Start dragging "ello".
1283 textfield_
->SelectRange(gfx::Range(1, 5));
1284 gfx::Point
point(GetCursorPositionX(3), 0);
1285 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, point
, point
,
1286 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1287 ui::EF_LEFT_MOUSE_BUTTON
);
1288 textfield_
->OnMousePressed(click_a
);
1289 EXPECT_TRUE(textfield_
->CanStartDragForView(textfield_
, click_a
.location(),
1291 operations
= textfield_
->GetDragOperationsForView(textfield_
,
1292 click_a
.location());
1293 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1295 textfield_
->WriteDragDataForView(NULL
, click_a
.location(), &data
);
1296 EXPECT_TRUE(data
.GetString(&string
));
1297 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1298 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1299 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1300 EXPECT_TRUE(custom_formats
.empty());
1302 // Drop "ello" after "w".
1303 const gfx::Point
kDropPoint(GetCursorPositionX(7), 0);
1304 EXPECT_TRUE(textfield_
->CanDrop(data
));
1305 ui::DropTargetEvent
drop_a(data
, kDropPoint
, kDropPoint
, operations
);
1306 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop_a
));
1307 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnPerformDrop(drop_a
));
1308 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1309 textfield_
->OnDragDone();
1311 // Undo/Redo the drag&drop change.
1312 SendKeyEvent(ui::VKEY_Z
, false, true);
1313 EXPECT_STR_EQ("hello world", textfield_
->text());
1314 SendKeyEvent(ui::VKEY_Z
, false, true);
1315 EXPECT_STR_EQ("", textfield_
->text());
1316 SendKeyEvent(ui::VKEY_Z
, false, true);
1317 EXPECT_STR_EQ("", textfield_
->text());
1318 SendKeyEvent(ui::VKEY_Z
, true, true);
1319 EXPECT_STR_EQ("hello world", textfield_
->text());
1320 SendKeyEvent(ui::VKEY_Z
, true, true);
1321 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1322 SendKeyEvent(ui::VKEY_Z
, true, true);
1323 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1326 TEST_F(TextfieldTest
, DragAndDrop_ToTheLeft
) {
1328 textfield_
->SetText(ASCIIToUTF16("hello world"));
1330 base::string16 string
;
1331 ui::OSExchangeData data
;
1334 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1336 // Start dragging " worl".
1337 textfield_
->SelectRange(gfx::Range(5, 10));
1338 gfx::Point
point(GetCursorPositionX(7), 0);
1339 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, point
, point
,
1340 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1341 ui::EF_LEFT_MOUSE_BUTTON
);
1342 textfield_
->OnMousePressed(click_a
);
1343 EXPECT_TRUE(textfield_
->CanStartDragForView(textfield_
, click_a
.location(),
1345 operations
= textfield_
->GetDragOperationsForView(textfield_
,
1346 click_a
.location());
1347 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1349 textfield_
->WriteDragDataForView(NULL
, click_a
.location(), &data
);
1350 EXPECT_TRUE(data
.GetString(&string
));
1351 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1352 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1353 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1354 EXPECT_TRUE(custom_formats
.empty());
1356 // Drop " worl" after "h".
1357 EXPECT_TRUE(textfield_
->CanDrop(data
));
1358 gfx::Point
drop_point(GetCursorPositionX(1), 0);
1359 ui::DropTargetEvent
drop_a(data
, drop_point
, drop_point
, operations
);
1360 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop_a
));
1361 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnPerformDrop(drop_a
));
1362 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1363 textfield_
->OnDragDone();
1365 // Undo/Redo the drag&drop change.
1366 SendKeyEvent(ui::VKEY_Z
, false, true);
1367 EXPECT_STR_EQ("hello world", textfield_
->text());
1368 SendKeyEvent(ui::VKEY_Z
, false, true);
1369 EXPECT_STR_EQ("", textfield_
->text());
1370 SendKeyEvent(ui::VKEY_Z
, false, true);
1371 EXPECT_STR_EQ("", textfield_
->text());
1372 SendKeyEvent(ui::VKEY_Z
, true, true);
1373 EXPECT_STR_EQ("hello world", textfield_
->text());
1374 SendKeyEvent(ui::VKEY_Z
, true, true);
1375 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1376 SendKeyEvent(ui::VKEY_Z
, true, true);
1377 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1380 TEST_F(TextfieldTest
, DragAndDrop_Canceled
) {
1382 textfield_
->SetText(ASCIIToUTF16("hello world"));
1384 // Start dragging "worl".
1385 textfield_
->SelectRange(gfx::Range(6, 10));
1386 gfx::Point
point(GetCursorPositionX(8), 0);
1387 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, point
, point
,
1388 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1389 ui::EF_LEFT_MOUSE_BUTTON
);
1390 textfield_
->OnMousePressed(click
);
1391 ui::OSExchangeData data
;
1392 textfield_
->WriteDragDataForView(NULL
, click
.location(), &data
);
1393 EXPECT_TRUE(textfield_
->CanDrop(data
));
1394 // Drag the text over somewhere valid, outside the current selection.
1395 gfx::Point
drop_point(GetCursorPositionX(2), 0);
1396 ui::DropTargetEvent
drop(data
, drop_point
, drop_point
,
1397 ui::DragDropTypes::DRAG_MOVE
);
1398 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop
));
1399 // "Cancel" the drag, via move and release over the selection, and OnDragDone.
1400 gfx::Point
drag_point(GetCursorPositionX(9), 0);
1401 ui::MouseEvent
drag(ui::ET_MOUSE_DRAGGED
, drag_point
, drag_point
,
1402 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1403 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, drag_point
, drag_point
,
1404 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1405 ui::EF_LEFT_MOUSE_BUTTON
);
1406 textfield_
->OnMouseDragged(drag
);
1407 textfield_
->OnMouseReleased(release
);
1408 textfield_
->OnDragDone();
1409 EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_
->text());
1412 TEST_F(TextfieldTest
, ReadOnlyTest
) {
1414 textfield_
->SetText(ASCIIToUTF16("read only"));
1415 textfield_
->SetReadOnly(true);
1416 EXPECT_TRUE(textfield_
->enabled());
1417 EXPECT_TRUE(textfield_
->IsFocusable());
1420 SendHomeEvent(shift
);
1421 EXPECT_EQ(0U, textfield_
->GetCursorPosition());
1422 SendEndEvent(shift
);
1423 EXPECT_EQ(9U, textfield_
->GetCursorPosition());
1425 SendKeyEvent(ui::VKEY_LEFT
, shift
, false);
1426 EXPECT_EQ(8U, textfield_
->GetCursorPosition());
1427 SendWordEvent(ui::VKEY_LEFT
, shift
);
1428 EXPECT_EQ(5U, textfield_
->GetCursorPosition());
1430 SendWordEvent(ui::VKEY_LEFT
, shift
);
1431 EXPECT_EQ(0U, textfield_
->GetCursorPosition());
1432 EXPECT_STR_EQ("read ", textfield_
->GetSelectedText());
1433 textfield_
->SelectAll(false);
1434 EXPECT_STR_EQ("read only", textfield_
->GetSelectedText());
1436 // Cut should be disabled.
1437 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1438 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
1439 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
1440 SendKeyEvent(ui::VKEY_X
, false, true);
1442 EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1443 EXPECT_STR_EQ("read only", textfield_
->text());
1445 // Paste should be disabled.
1446 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
1447 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
1448 SendKeyEvent(ui::VKEY_V
, false, true);
1449 SendAlternatePaste();
1450 EXPECT_STR_EQ("read only", textfield_
->text());
1452 // Copy should work normally.
1453 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1454 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
1455 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
1456 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1457 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1458 SendKeyEvent(ui::VKEY_C
, false, true);
1459 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1460 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1461 SendAlternateCopy();
1462 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1464 // SetText should work even in read only mode.
1465 textfield_
->SetText(ASCIIToUTF16(" four five six "));
1466 EXPECT_STR_EQ(" four five six ", textfield_
->text());
1468 textfield_
->SelectAll(false);
1469 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1471 // Text field is unmodifiable and selection shouldn't change.
1472 SendKeyEvent(ui::VKEY_DELETE
);
1473 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1474 SendKeyEvent(ui::VKEY_BACK
);
1475 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1476 SendKeyEvent(ui::VKEY_T
);
1477 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1480 TEST_F(TextfieldTest
, TextInputClientTest
) {
1482 ui::TextInputClient
* client
= textfield_
;
1483 EXPECT_TRUE(client
);
1484 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT
, client
->GetTextInputType());
1486 textfield_
->SetText(ASCIIToUTF16("0123456789"));
1488 EXPECT_TRUE(client
->GetTextRange(&range
));
1489 EXPECT_EQ(0U, range
.start());
1490 EXPECT_EQ(10U, range
.end());
1492 EXPECT_TRUE(client
->SetSelectionRange(gfx::Range(1, 4)));
1493 EXPECT_TRUE(client
->GetSelectionRange(&range
));
1494 EXPECT_EQ(gfx::Range(1, 4), range
);
1496 base::string16 substring
;
1497 EXPECT_TRUE(client
->GetTextFromRange(range
, &substring
));
1498 EXPECT_STR_EQ("123", substring
);
1500 EXPECT_TRUE(client
->DeleteRange(range
));
1501 EXPECT_STR_EQ("0456789", textfield_
->text());
1503 ui::CompositionText composition
;
1504 composition
.text
= UTF8ToUTF16("321");
1505 // Set composition through input method.
1506 input_method_
->Clear();
1507 input_method_
->SetCompositionTextForNextKey(composition
);
1508 textfield_
->clear();
1510 on_before_user_action_
= on_after_user_action_
= 0;
1512 // Send a key to trigger MockInputMethod::DispatchKeyEvent(). Note the
1513 // specific VKEY isn't used (MockInputMethod will mock a ui::VKEY_PROCESSKEY
1514 // whenever it has a test composition). However, on Mac, it can't be a letter
1515 // (e.g. VKEY_A) since all native character events on Mac are unicode events
1516 // and don't have a meaningful ui::KeyEvent that would trigger
1517 // DispatchKeyEvent().
1518 SendKeyEvent(ui::VKEY_RETURN
);
1520 EXPECT_TRUE(textfield_
->key_received());
1521 EXPECT_FALSE(textfield_
->key_handled());
1522 EXPECT_TRUE(client
->HasCompositionText());
1523 EXPECT_TRUE(client
->GetCompositionTextRange(&range
));
1524 EXPECT_STR_EQ("0321456789", textfield_
->text());
1525 EXPECT_EQ(gfx::Range(1, 4), range
);
1526 EXPECT_EQ(1, on_before_user_action_
);
1527 EXPECT_EQ(1, on_after_user_action_
);
1529 input_method_
->SetResultTextForNextKey(UTF8ToUTF16("123"));
1530 on_before_user_action_
= on_after_user_action_
= 0;
1531 textfield_
->clear();
1532 SendKeyEvent(ui::VKEY_RETURN
);
1533 EXPECT_TRUE(textfield_
->key_received());
1534 EXPECT_FALSE(textfield_
->key_handled());
1535 EXPECT_FALSE(client
->HasCompositionText());
1536 EXPECT_FALSE(input_method_
->cancel_composition_called());
1537 EXPECT_STR_EQ("0123456789", textfield_
->text());
1538 EXPECT_EQ(1, on_before_user_action_
);
1539 EXPECT_EQ(1, on_after_user_action_
);
1541 input_method_
->Clear();
1542 input_method_
->SetCompositionTextForNextKey(composition
);
1543 textfield_
->clear();
1544 SendKeyEvent(ui::VKEY_RETURN
);
1545 EXPECT_TRUE(client
->HasCompositionText());
1546 EXPECT_STR_EQ("0123321456789", textfield_
->text());
1548 on_before_user_action_
= on_after_user_action_
= 0;
1549 textfield_
->clear();
1550 SendKeyEvent(ui::VKEY_RIGHT
);
1551 EXPECT_FALSE(client
->HasCompositionText());
1552 EXPECT_TRUE(input_method_
->cancel_composition_called());
1553 EXPECT_TRUE(textfield_
->key_received());
1554 EXPECT_TRUE(textfield_
->key_handled());
1555 EXPECT_STR_EQ("0123321456789", textfield_
->text());
1556 EXPECT_EQ(8U, textfield_
->GetCursorPosition());
1557 EXPECT_EQ(1, on_before_user_action_
);
1558 EXPECT_EQ(1, on_after_user_action_
);
1560 textfield_
->clear();
1561 textfield_
->SetText(ASCIIToUTF16("0123456789"));
1562 EXPECT_TRUE(client
->SetSelectionRange(gfx::Range(5, 5)));
1563 client
->ExtendSelectionAndDelete(4, 2);
1564 EXPECT_STR_EQ("0789", textfield_
->text());
1566 // On{Before,After}UserAction should be called by whatever user action
1567 // triggers clearing or setting a selection if appropriate.
1568 on_before_user_action_
= on_after_user_action_
= 0;
1569 textfield_
->clear();
1570 textfield_
->ClearSelection();
1571 textfield_
->SelectAll(false);
1572 EXPECT_EQ(0, on_before_user_action_
);
1573 EXPECT_EQ(0, on_after_user_action_
);
1575 input_method_
->Clear();
1577 // Changing the Textfield to readonly shouldn't change the input client, since
1578 // it's still required for selections and clipboard copy.
1579 ui::TextInputClient
* text_input_client
= textfield_
;
1580 EXPECT_TRUE(text_input_client
);
1581 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1582 textfield_
->SetReadOnly(true);
1583 EXPECT_TRUE(input_method_
->text_input_type_changed());
1584 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1586 input_method_
->Clear();
1587 textfield_
->SetReadOnly(false);
1588 EXPECT_TRUE(input_method_
->text_input_type_changed());
1589 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1591 input_method_
->Clear();
1592 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
1593 EXPECT_TRUE(input_method_
->text_input_type_changed());
1596 TEST_F(TextfieldTest
, UndoRedoTest
) {
1598 SendKeyEvent(ui::VKEY_A
);
1599 EXPECT_STR_EQ("a", textfield_
->text());
1600 SendKeyEvent(ui::VKEY_Z
, false, true);
1601 EXPECT_STR_EQ("", textfield_
->text());
1602 SendKeyEvent(ui::VKEY_Z
, false, true);
1603 EXPECT_STR_EQ("", textfield_
->text());
1604 SendKeyEvent(ui::VKEY_Z
, true, true);
1605 EXPECT_STR_EQ("a", textfield_
->text());
1606 SendKeyEvent(ui::VKEY_Z
, true, true);
1607 EXPECT_STR_EQ("a", textfield_
->text());
1610 textfield_
->AppendText(ASCIIToUTF16("b"));
1611 last_contents_
.clear(); // AppendText doesn't call ContentsChanged.
1612 EXPECT_STR_EQ("ab", textfield_
->text());
1613 SendKeyEvent(ui::VKEY_Z
, false, true);
1614 EXPECT_STR_EQ("a", textfield_
->text());
1615 SendKeyEvent(ui::VKEY_Z
, true, true);
1616 EXPECT_STR_EQ("ab", textfield_
->text());
1619 SendKeyEvent(ui::VKEY_C
);
1620 // Undo'ing append moves the cursor to the end for now.
1621 // A no-op SetText won't add a new edit; see TextfieldModel::SetText.
1622 EXPECT_STR_EQ("abc", textfield_
->text());
1623 textfield_
->SetText(ASCIIToUTF16("abc"));
1624 EXPECT_STR_EQ("abc", textfield_
->text());
1625 SendKeyEvent(ui::VKEY_Z
, false, true);
1626 EXPECT_STR_EQ("ab", textfield_
->text());
1627 SendKeyEvent(ui::VKEY_Z
, true, true);
1628 EXPECT_STR_EQ("abc", textfield_
->text());
1629 SendKeyEvent(ui::VKEY_Z
, true, true);
1630 EXPECT_STR_EQ("abc", textfield_
->text());
1631 textfield_
->SetText(ASCIIToUTF16("123"));
1632 textfield_
->SetText(ASCIIToUTF16("123"));
1633 EXPECT_STR_EQ("123", textfield_
->text());
1634 SendKeyEvent(ui::VKEY_END
, false, false);
1635 SendKeyEvent(ui::VKEY_4
, false, false);
1636 EXPECT_STR_EQ("1234", textfield_
->text());
1637 last_contents_
.clear();
1638 SendKeyEvent(ui::VKEY_Z
, false, true);
1639 EXPECT_STR_EQ("123", textfield_
->text());
1640 SendKeyEvent(ui::VKEY_Z
, false, true);
1641 // the insert edit "c" and set edit "123" are merged to single edit,
1642 // so text becomes "ab" after undo.
1643 EXPECT_STR_EQ("ab", textfield_
->text());
1644 SendKeyEvent(ui::VKEY_Z
, false, true);
1645 EXPECT_STR_EQ("a", textfield_
->text());
1646 SendKeyEvent(ui::VKEY_Z
, true, true);
1647 EXPECT_STR_EQ("ab", textfield_
->text());
1648 SendKeyEvent(ui::VKEY_Z
, true, true);
1649 EXPECT_STR_EQ("123", textfield_
->text());
1650 SendKeyEvent(ui::VKEY_Z
, true, true);
1651 EXPECT_STR_EQ("1234", textfield_
->text());
1653 // Undoing to the same text shouldn't call ContentsChanged.
1654 SendKeyEvent(ui::VKEY_A
, false, true); // select all
1655 SendKeyEvent(ui::VKEY_A
);
1656 EXPECT_STR_EQ("a", textfield_
->text());
1657 SendKeyEvent(ui::VKEY_B
);
1658 SendKeyEvent(ui::VKEY_C
);
1659 EXPECT_STR_EQ("abc", textfield_
->text());
1660 SendKeyEvent(ui::VKEY_Z
, false, true);
1661 EXPECT_STR_EQ("1234", textfield_
->text());
1662 SendKeyEvent(ui::VKEY_Z
, true, true);
1663 EXPECT_STR_EQ("abc", textfield_
->text());
1666 SendKeyEvent(ui::VKEY_BACK
);
1667 EXPECT_STR_EQ("ab", textfield_
->text());
1668 SendHomeEvent(false);
1669 SendKeyEvent(ui::VKEY_DELETE
);
1670 EXPECT_STR_EQ("b", textfield_
->text());
1671 SendKeyEvent(ui::VKEY_A
, false, true);
1672 SendKeyEvent(ui::VKEY_DELETE
);
1673 EXPECT_STR_EQ("", textfield_
->text());
1674 SendKeyEvent(ui::VKEY_Z
, false, true);
1675 EXPECT_STR_EQ("b", textfield_
->text());
1676 SendKeyEvent(ui::VKEY_Z
, false, true);
1677 EXPECT_STR_EQ("ab", textfield_
->text());
1678 SendKeyEvent(ui::VKEY_Z
, false, true);
1679 EXPECT_STR_EQ("abc", textfield_
->text());
1680 SendKeyEvent(ui::VKEY_Z
, true, true);
1681 EXPECT_STR_EQ("ab", textfield_
->text());
1682 SendKeyEvent(ui::VKEY_Z
, true, true);
1683 EXPECT_STR_EQ("b", textfield_
->text());
1684 SendKeyEvent(ui::VKEY_Z
, true, true);
1685 EXPECT_STR_EQ("", textfield_
->text());
1686 SendKeyEvent(ui::VKEY_Z
, true, true);
1687 EXPECT_STR_EQ("", textfield_
->text());
1690 // Most platforms support Ctrl+Y as an alternative to Ctrl+Shift+Z, but on Mac
1691 // that is bound to "Show full history", so is not mapped as an editing
1692 // command. So, on Mac, send Cmd+Shift+Z.
1693 #if !defined(OS_MACOSX)
1695 // Test that Ctrl+Y works for Redo, as well as Ctrl+Shift+Z.
1696 TEST_F(TextfieldTest
, RedoWithCtrlY
) {
1698 SendKeyEvent(ui::VKEY_A
);
1699 EXPECT_STR_EQ("a", textfield_
->text());
1700 SendKeyEvent(ui::VKEY_Z
, false, true);
1701 EXPECT_STR_EQ("", textfield_
->text());
1702 SendKeyEvent(ui::VKEY_Y
, false, true);
1703 EXPECT_STR_EQ("a", textfield_
->text());
1704 SendKeyEvent(ui::VKEY_Z
, false, true);
1705 EXPECT_STR_EQ("", textfield_
->text());
1706 SendKeyEvent(ui::VKEY_Z
, true, true);
1707 EXPECT_STR_EQ("a", textfield_
->text());
1710 #endif // !defined(OS_MACOSX)
1712 TEST_F(TextfieldTest
, CutCopyPaste
) {
1715 // Ensure IDS_APP_CUT cuts.
1716 textfield_
->SetText(ASCIIToUTF16("123"));
1717 textfield_
->SelectAll(false);
1718 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
1719 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
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 [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
1725 textfield_
->SetText(ASCIIToUTF16("456"));
1726 textfield_
->SelectAll(false);
1727 SendKeyEvent(ui::VKEY_X
, true, false, true, false);
1728 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1729 EXPECT_STR_EQ("456", textfield_
->text());
1730 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1731 SendKeyEvent(ui::VKEY_X
, false, true);
1732 EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1733 EXPECT_STR_EQ("", textfield_
->text());
1734 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1736 // Ensure [Shift]+[Delete] cuts.
1737 textfield_
->SetText(ASCIIToUTF16("123"));
1738 textfield_
->SelectAll(false);
1740 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1741 EXPECT_STR_EQ("", textfield_
->text());
1742 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1744 // Ensure IDS_APP_COPY copies.
1745 textfield_
->SetText(ASCIIToUTF16("789"));
1746 textfield_
->SelectAll(false);
1747 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
1748 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
1749 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1750 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1752 // Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
1753 textfield_
->SetText(ASCIIToUTF16("012"));
1754 textfield_
->SelectAll(false);
1755 SendKeyEvent(ui::VKEY_C
, true, false, true, false);
1756 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1757 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1758 SendKeyEvent(ui::VKEY_C
, false, true);
1759 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1760 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1762 // Ensure [Ctrl]+[Insert] copies.
1763 textfield_
->SetText(ASCIIToUTF16("345"));
1764 textfield_
->SelectAll(false);
1765 SendAlternateCopy();
1766 EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1767 EXPECT_STR_EQ("345", textfield_
->text());
1768 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1770 // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
1771 // also ensure that [Ctrl]+[Alt]+[V] does nothing.
1772 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "abc");
1773 textfield_
->SetText(base::string16());
1774 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
1775 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
1776 EXPECT_STR_EQ("abc", textfield_
->text());
1777 SendKeyEvent(ui::VKEY_V
, false, true);
1778 EXPECT_STR_EQ("abcabc", textfield_
->text());
1779 SendAlternatePaste();
1780 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1781 SendKeyEvent(ui::VKEY_V
, true, false, true, false);
1782 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1784 // Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
1785 textfield_
->SelectAll(false);
1786 SendKeyEvent(ui::VKEY_INSERT
, true, true);
1787 EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1788 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1789 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1792 TEST_F(TextfieldTest
, OvertypeMode
) {
1794 // Overtype mode should be disabled (no-op [Insert]).
1795 textfield_
->SetText(ASCIIToUTF16("2"));
1796 const bool shift
= false;
1797 SendHomeEvent(shift
);
1798 // Note: On Mac, there is no insert key. Insert sends kVK_Help. Currently,
1799 // since there is no overtype on toolkit-views, the behavior happens to match.
1800 // However, there's no enable-overtype equivalent key combination on OSX.
1801 SendKeyEvent(ui::VKEY_INSERT
);
1802 SendKeyEvent(ui::VKEY_1
, false, false);
1803 EXPECT_STR_EQ("12", textfield_
->text());
1806 TEST_F(TextfieldTest
, TextCursorDisplayTest
) {
1808 // LTR-RTL string in LTR context.
1810 EXPECT_STR_EQ("a", textfield_
->text());
1811 int x
= GetCursorBounds().x();
1815 EXPECT_STR_EQ("ab", textfield_
->text());
1816 x
= GetCursorBounds().x();
1817 EXPECT_LT(prev_x
, x
);
1820 SendKeyEvent(0x05E1);
1821 EXPECT_EQ(WideToUTF16(L
"ab\x05E1"), textfield_
->text());
1822 x
= GetCursorBounds().x();
1823 EXPECT_GE(1, std::abs(x
- prev_x
));
1825 SendKeyEvent(0x05E2);
1826 EXPECT_EQ(WideToUTF16(L
"ab\x05E1\x5E2"), textfield_
->text());
1827 x
= GetCursorBounds().x();
1828 EXPECT_GE(1, std::abs(x
- prev_x
));
1831 SendKeyEvent(ui::VKEY_A
, false, true);
1832 SendKeyEvent(ui::VKEY_DELETE
);
1834 // RTL-LTR string in LTR context.
1835 SendKeyEvent(0x05E1);
1836 EXPECT_EQ(WideToUTF16(L
"\x05E1"), textfield_
->text());
1837 x
= GetCursorBounds().x();
1838 EXPECT_EQ(GetDisplayRect().x(), x
);
1841 SendKeyEvent(0x05E2);
1842 EXPECT_EQ(WideToUTF16(L
"\x05E1\x05E2"), textfield_
->text());
1843 x
= GetCursorBounds().x();
1844 EXPECT_GE(1, std::abs(x
- prev_x
));
1847 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"a"), textfield_
->text());
1848 x
= GetCursorBounds().x();
1849 EXPECT_LT(prev_x
, x
);
1853 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"ab"), textfield_
->text());
1854 x
= GetCursorBounds().x();
1855 EXPECT_LT(prev_x
, x
);
1858 TEST_F(TextfieldTest
, TextCursorDisplayInRTLTest
) {
1859 std::string locale
= l10n_util::GetApplicationLocale("");
1860 base::i18n::SetICUDefaultLocale("he");
1863 // LTR-RTL string in RTL context.
1865 EXPECT_STR_EQ("a", textfield_
->text());
1866 int x
= GetCursorBounds().x();
1867 EXPECT_EQ(GetDisplayRect().right() - 1, x
);
1871 EXPECT_STR_EQ("ab", textfield_
->text());
1872 x
= GetCursorBounds().x();
1873 EXPECT_GE(1, std::abs(x
- prev_x
));
1875 SendKeyEvent(0x05E1);
1876 EXPECT_EQ(WideToUTF16(L
"ab\x05E1"), textfield_
->text());
1877 x
= GetCursorBounds().x();
1878 EXPECT_GT(prev_x
, x
);
1881 SendKeyEvent(0x05E2);
1882 EXPECT_EQ(WideToUTF16(L
"ab\x05E1\x5E2"), textfield_
->text());
1883 x
= GetCursorBounds().x();
1884 EXPECT_GT(prev_x
, x
);
1887 SendKeyEvent(ui::VKEY_A
, false, true);
1888 SendKeyEvent(ui::VKEY_DELETE
);
1890 // RTL-LTR string in RTL context.
1891 SendKeyEvent(0x05E1);
1892 EXPECT_EQ(WideToUTF16(L
"\x05E1"), textfield_
->text());
1893 x
= GetCursorBounds().x();
1896 SendKeyEvent(0x05E2);
1897 EXPECT_EQ(WideToUTF16(L
"\x05E1\x05E2"), textfield_
->text());
1898 x
= GetCursorBounds().x();
1899 EXPECT_GT(prev_x
, x
);
1903 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"a"), textfield_
->text());
1904 x
= GetCursorBounds().x();
1905 EXPECT_GE(1, std::abs(x
- prev_x
));
1909 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"ab"), textfield_
->text());
1910 x
= GetCursorBounds().x();
1911 EXPECT_GE(1, std::abs(x
- prev_x
));
1914 base::i18n::SetICUDefaultLocale(locale
);
1917 TEST_F(TextfieldTest
, HitInsideTextAreaTest
) {
1919 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
1920 std::vector
<gfx::Rect
> cursor_bounds
;
1922 // Save each cursor bound.
1923 gfx::SelectionModel
sel(0, gfx::CURSOR_FORWARD
);
1924 cursor_bounds
.push_back(GetCursorBounds(sel
));
1926 sel
= gfx::SelectionModel(1, gfx::CURSOR_BACKWARD
);
1927 gfx::Rect bound
= GetCursorBounds(sel
);
1928 sel
= gfx::SelectionModel(1, gfx::CURSOR_FORWARD
);
1929 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1930 cursor_bounds
.push_back(bound
);
1932 // Check that a cursor at the end of the Latin portion of the text is at the
1933 // same position as a cursor placed at the end of the RTL Hebrew portion.
1934 sel
= gfx::SelectionModel(2, gfx::CURSOR_BACKWARD
);
1935 bound
= GetCursorBounds(sel
);
1936 sel
= gfx::SelectionModel(4, gfx::CURSOR_BACKWARD
);
1937 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1938 cursor_bounds
.push_back(bound
);
1940 sel
= gfx::SelectionModel(3, gfx::CURSOR_BACKWARD
);
1941 bound
= GetCursorBounds(sel
);
1942 sel
= gfx::SelectionModel(3, gfx::CURSOR_FORWARD
);
1943 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1944 cursor_bounds
.push_back(bound
);
1946 sel
= gfx::SelectionModel(2, gfx::CURSOR_FORWARD
);
1947 bound
= GetCursorBounds(sel
);
1948 sel
= gfx::SelectionModel(4, gfx::CURSOR_FORWARD
);
1949 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1950 cursor_bounds
.push_back(bound
);
1952 // Expected cursor position when clicking left and right of each character.
1953 size_t cursor_pos_expected
[] = {0, 1, 1, 2, 4, 3, 3, 2};
1956 for (int i
= 0; i
< static_cast<int>(cursor_bounds
.size() - 1); ++i
) {
1957 int half_width
= (cursor_bounds
[i
+ 1].x() - cursor_bounds
[i
].x()) / 2;
1958 MouseClick(cursor_bounds
[i
], half_width
/ 2);
1959 EXPECT_EQ(cursor_pos_expected
[index
++], textfield_
->GetCursorPosition());
1961 // To avoid trigger double click. Not using sleep() since it takes longer
1962 // for the test to run if using sleep().
1963 NonClientMouseClick();
1965 MouseClick(cursor_bounds
[i
+ 1], - (half_width
/ 2));
1966 EXPECT_EQ(cursor_pos_expected
[index
++], textfield_
->GetCursorPosition());
1968 NonClientMouseClick();
1972 TEST_F(TextfieldTest
, HitOutsideTextAreaTest
) {
1975 // LTR-RTL string in LTR context.
1976 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
1978 const bool shift
= false;
1979 SendHomeEvent(shift
);
1980 gfx::Rect bound
= GetCursorBounds();
1981 MouseClick(bound
, -10);
1982 EXPECT_EQ(bound
, GetCursorBounds());
1984 SendEndEvent(shift
);
1985 bound
= GetCursorBounds();
1986 MouseClick(bound
, 10);
1987 EXPECT_EQ(bound
, GetCursorBounds());
1989 NonClientMouseClick();
1991 // RTL-LTR string in LTR context.
1992 textfield_
->SetText(WideToUTF16(L
"\x05E1\x5E2" L
"ab"));
1994 SendHomeEvent(shift
);
1995 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());
2005 TEST_F(TextfieldTest
, HitOutsideTextAreaInRTLTest
) {
2006 std::string locale
= l10n_util::GetApplicationLocale("");
2007 base::i18n::SetICUDefaultLocale("he");
2011 // RTL-LTR string in RTL context.
2012 textfield_
->SetText(WideToUTF16(L
"\x05E1\x5E2" L
"ab"));
2013 const bool shift
= false;
2014 SendHomeEvent(shift
);
2015 gfx::Rect bound
= GetCursorBounds();
2016 MouseClick(bound
, 10);
2017 EXPECT_EQ(bound
, GetCursorBounds());
2019 SendEndEvent(shift
);
2020 bound
= GetCursorBounds();
2021 MouseClick(bound
, -10);
2022 EXPECT_EQ(bound
, GetCursorBounds());
2024 NonClientMouseClick();
2026 // LTR-RTL string in RTL context.
2027 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
2028 SendHomeEvent(shift
);
2029 bound
= GetCursorBounds();
2030 MouseClick(bound
, -10);
2031 EXPECT_EQ(bound
, GetCursorBounds());
2033 SendEndEvent(shift
);
2034 bound
= GetCursorBounds();
2035 MouseClick(bound
, 10);
2036 EXPECT_EQ(bound
, GetCursorBounds());
2039 base::i18n::SetICUDefaultLocale(locale
);
2042 TEST_F(TextfieldTest
, OverflowTest
) {
2046 for (int i
= 0; i
< 500; ++i
)
2048 SendKeyEvent(kHebrewLetterSamekh
);
2049 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2051 // Test mouse pointing.
2052 MouseClick(GetCursorBounds(), -1);
2053 EXPECT_EQ(500U, textfield_
->GetCursorPosition());
2056 SendKeyEvent(ui::VKEY_A
, false, true);
2057 SendKeyEvent(ui::VKEY_DELETE
);
2059 for (int i
= 0; i
< 500; ++i
)
2060 SendKeyEvent(kHebrewLetterSamekh
);
2062 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2064 MouseClick(GetCursorBounds(), -1);
2065 EXPECT_EQ(501U, textfield_
->GetCursorPosition());
2068 TEST_F(TextfieldTest
, OverflowInRTLTest
) {
2069 std::string locale
= l10n_util::GetApplicationLocale("");
2070 base::i18n::SetICUDefaultLocale("he");
2075 for (int i
= 0; i
< 500; ++i
)
2077 SendKeyEvent(kHebrewLetterSamekh
);
2078 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2080 MouseClick(GetCursorBounds(), 1);
2081 EXPECT_EQ(501U, textfield_
->GetCursorPosition());
2084 SendKeyEvent(ui::VKEY_A
, false, true);
2085 SendKeyEvent(ui::VKEY_DELETE
);
2087 for (int i
= 0; i
< 500; ++i
)
2088 SendKeyEvent(kHebrewLetterSamekh
);
2090 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2092 MouseClick(GetCursorBounds(), 1);
2093 EXPECT_EQ(500U, textfield_
->GetCursorPosition());
2096 base::i18n::SetICUDefaultLocale(locale
);
2099 TEST_F(TextfieldTest
, GetCompositionCharacterBoundsTest
) {
2101 ui::CompositionText composition
;
2102 composition
.text
= UTF8ToUTF16("abc123");
2103 const uint32 char_count
= static_cast<uint32
>(composition
.text
.length());
2104 ui::TextInputClient
* client
= textfield_
;
2106 // Compare the composition character bounds with surrounding cursor bounds.
2107 for (uint32 i
= 0; i
< char_count
; ++i
) {
2108 composition
.selection
= gfx::Range(i
);
2109 client
->SetCompositionText(composition
);
2110 gfx::Point cursor_origin
= GetCursorBounds().origin();
2111 views::View::ConvertPointToScreen(textfield_
, &cursor_origin
);
2113 composition
.selection
= gfx::Range(i
+ 1);
2114 client
->SetCompositionText(composition
);
2115 gfx::Point next_cursor_bottom_left
= GetCursorBounds().bottom_left();
2116 views::View::ConvertPointToScreen(textfield_
, &next_cursor_bottom_left
);
2118 gfx::Rect character
;
2119 EXPECT_TRUE(client
->GetCompositionCharacterBounds(i
, &character
));
2120 EXPECT_EQ(character
.origin(), cursor_origin
) << " i=" << i
;
2121 EXPECT_EQ(character
.bottom_right(), next_cursor_bottom_left
) << " i=" << i
;
2124 // Return false if the index is out of range.
2126 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
, &rect
));
2127 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
+ 1, &rect
));
2128 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
+ 100, &rect
));
2131 TEST_F(TextfieldTest
, GetCompositionCharacterBounds_ComplexText
) {
2134 const base::char16 kUtf16Chars
[] = {
2137 // U+1F408 (CAT) as surrogate pair
2139 // U+5642 as Ideographic Variation Sequences
2140 0x5642, 0xDB40, 0xDD00,
2141 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences
2146 const size_t kUtf16CharsCount
= arraysize(kUtf16Chars
);
2148 ui::CompositionText composition
;
2149 composition
.text
.assign(kUtf16Chars
, kUtf16Chars
+ kUtf16CharsCount
);
2150 ui::TextInputClient
* client
= textfield_
;
2151 client
->SetCompositionText(composition
);
2153 // Make sure GetCompositionCharacterBounds never fails for index.
2154 gfx::Rect rects
[kUtf16CharsCount
];
2155 gfx::Rect prev_cursor
= GetCursorBounds();
2156 for (uint32 i
= 0; i
< kUtf16CharsCount
; ++i
)
2157 EXPECT_TRUE(client
->GetCompositionCharacterBounds(i
, &rects
[i
]));
2159 // Here we might expect the following results but it actually depends on how
2160 // Uniscribe or HarfBuzz treats them with given font.
2161 // - rects[1] == rects[2]
2162 // - rects[3] == rects[4] == rects[5]
2163 // - rects[6] == rects[7]
2166 // The word we select by double clicking should remain selected regardless of
2167 // where we drag the mouse afterwards without releasing the left button.
2168 TEST_F(TextfieldTest
, KeepInitiallySelectedWord
) {
2171 textfield_
->SetText(ASCIIToUTF16("abc def ghi"));
2173 textfield_
->SelectRange(gfx::Range(5, 5));
2174 const gfx::Rect middle_cursor
= GetCursorBounds();
2175 textfield_
->SelectRange(gfx::Range(0, 0));
2176 const gfx::Point beginning
= GetCursorBounds().origin();
2178 // Double click, but do not release the left button.
2179 MouseClick(middle_cursor
, 0);
2180 const gfx::Point
middle(middle_cursor
.x(),
2181 middle_cursor
.y() + middle_cursor
.height() / 2);
2182 ui::MouseEvent
press_event(ui::ET_MOUSE_PRESSED
, middle
, middle
,
2183 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2184 ui::EF_LEFT_MOUSE_BUTTON
);
2185 textfield_
->OnMousePressed(press_event
);
2186 EXPECT_EQ(gfx::Range(4, 7), textfield_
->GetSelectedRange());
2188 // Drag the mouse to the beginning of the textfield.
2189 ui::MouseEvent
drag_event(ui::ET_MOUSE_DRAGGED
, beginning
, beginning
,
2190 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
2191 textfield_
->OnMouseDragged(drag_event
);
2192 EXPECT_EQ(gfx::Range(7, 0), textfield_
->GetSelectedRange());
2195 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2196 // flaky: http://crbug.com/396477
2197 TEST_F(TextfieldTest
, DISABLED_SelectionClipboard
) {
2199 textfield_
->SetText(ASCIIToUTF16("0123"));
2200 gfx::Point
point_1(GetCursorPositionX(1), 0);
2201 gfx::Point
point_2(GetCursorPositionX(2), 0);
2202 gfx::Point
point_3(GetCursorPositionX(3), 0);
2203 gfx::Point
point_4(GetCursorPositionX(4), 0);
2205 // Text selected by the mouse should be placed on the selection clipboard.
2206 ui::MouseEvent
press(ui::ET_MOUSE_PRESSED
, point_1
, point_1
,
2207 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2208 ui::EF_LEFT_MOUSE_BUTTON
);
2209 textfield_
->OnMousePressed(press
);
2210 ui::MouseEvent
drag(ui::ET_MOUSE_DRAGGED
, point_3
, point_3
,
2211 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2212 ui::EF_LEFT_MOUSE_BUTTON
);
2213 textfield_
->OnMouseDragged(drag
);
2214 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, point_3
, point_3
,
2215 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2216 ui::EF_LEFT_MOUSE_BUTTON
);
2217 textfield_
->OnMouseReleased(release
);
2218 EXPECT_EQ(gfx::Range(1, 3), textfield_
->GetSelectedRange());
2219 EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2221 // Select-all should update the selection clipboard.
2222 SendKeyEvent(ui::VKEY_A
, false, true);
2223 EXPECT_EQ(gfx::Range(0, 4), textfield_
->GetSelectedRange());
2224 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2225 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2227 // Shift-click selection modifications should update the clipboard.
2228 NonClientMouseClick();
2229 ui::MouseEvent
press_2(ui::ET_MOUSE_PRESSED
, point_2
, point_2
,
2230 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2231 ui::EF_LEFT_MOUSE_BUTTON
);
2232 press_2
.set_flags(press_2
.flags() | ui::EF_SHIFT_DOWN
);
2233 #if defined(USE_X11)
2234 ui::UpdateX11EventForFlags(&press_2
);
2236 textfield_
->OnMousePressed(press_2
);
2237 ui::MouseEvent
release_2(ui::ET_MOUSE_RELEASED
, point_2
, point_2
,
2238 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2239 ui::EF_LEFT_MOUSE_BUTTON
);
2240 textfield_
->OnMouseReleased(release_2
);
2241 EXPECT_EQ(gfx::Range(0, 2), textfield_
->GetSelectedRange());
2242 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2243 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2245 // Shift-Left/Right should update the selection clipboard.
2246 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
2247 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2248 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2249 SendKeyEvent(ui::VKEY_LEFT
, true, false);
2250 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2251 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2252 SendKeyEvent(ui::VKEY_RIGHT
, true, true);
2253 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2254 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2256 // Moving the cursor without a selection should not change the clipboard.
2257 SendKeyEvent(ui::VKEY_LEFT
, false, false);
2258 EXPECT_EQ(gfx::Range(0, 0), textfield_
->GetSelectedRange());
2259 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2260 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2262 // Middle clicking should paste at the mouse (not cursor) location.
2263 // The cursor should be placed at the end of the pasted text.
2264 ui::MouseEvent
middle(ui::ET_MOUSE_PRESSED
, point_4
, point_4
,
2265 ui::EventTimeForNow(), ui::EF_MIDDLE_MOUSE_BUTTON
,
2266 ui::EF_MIDDLE_MOUSE_BUTTON
);
2267 textfield_
->OnMousePressed(middle
);
2268 EXPECT_STR_EQ("01230123", textfield_
->text());
2269 EXPECT_EQ(gfx::Range(8, 8), textfield_
->GetSelectedRange());
2270 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2272 // Middle clicking on an unfocused textfield should focus it and paste.
2273 textfield_
->GetFocusManager()->ClearFocus();
2274 EXPECT_FALSE(textfield_
->HasFocus());
2275 textfield_
->OnMousePressed(middle
);
2276 EXPECT_TRUE(textfield_
->HasFocus());
2277 EXPECT_STR_EQ("012301230123", textfield_
->text());
2278 EXPECT_EQ(gfx::Range(8, 8), textfield_
->GetSelectedRange());
2279 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2281 // Middle clicking with an empty selection clipboard should still focus.
2282 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, std::string());
2283 textfield_
->GetFocusManager()->ClearFocus();
2284 EXPECT_FALSE(textfield_
->HasFocus());
2285 textfield_
->OnMousePressed(middle
);
2286 EXPECT_TRUE(textfield_
->HasFocus());
2287 EXPECT_STR_EQ("012301230123", textfield_
->text());
2288 EXPECT_EQ(gfx::Range(4, 4), textfield_
->GetSelectedRange());
2289 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
).empty());
2291 // Middle clicking in the selection should clear the clipboard and selection.
2292 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "foo");
2293 textfield_
->SelectRange(gfx::Range(2, 6));
2294 textfield_
->OnMousePressed(middle
);
2295 EXPECT_STR_EQ("012301230123", textfield_
->text());
2296 EXPECT_EQ(gfx::Range(6, 6), textfield_
->GetSelectedRange());
2297 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
).empty());
2299 // Double and triple clicking should update the clipboard contents.
2300 textfield_
->SetText(ASCIIToUTF16("ab cd ef"));
2301 gfx::Point
word(GetCursorPositionX(4), 0);
2302 ui::MouseEvent
press_word(ui::ET_MOUSE_PRESSED
, word
, word
,
2303 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2304 ui::EF_LEFT_MOUSE_BUTTON
);
2305 textfield_
->OnMousePressed(press_word
);
2306 ui::MouseEvent
release_word(ui::ET_MOUSE_RELEASED
, word
, word
,
2307 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2308 ui::EF_LEFT_MOUSE_BUTTON
);
2309 textfield_
->OnMouseReleased(release_word
);
2310 ui::MouseEvent
double_click(ui::ET_MOUSE_PRESSED
, word
, word
,
2311 ui::EventTimeForNow(),
2312 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_DOUBLE_CLICK
,
2313 ui::EF_LEFT_MOUSE_BUTTON
);
2314 textfield_
->OnMousePressed(double_click
);
2315 textfield_
->OnMouseReleased(release_word
);
2316 EXPECT_EQ(gfx::Range(3, 5), textfield_
->GetSelectedRange());
2317 EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2318 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2319 textfield_
->OnMousePressed(press_word
);
2320 textfield_
->OnMouseReleased(release_word
);
2321 EXPECT_EQ(gfx::Range(0, 8), textfield_
->GetSelectedRange());
2322 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2323 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2325 // Selecting a range of text without any user interaction should not change
2326 // the clipboard content.
2327 textfield_
->SelectRange(gfx::Range(0, 3));
2328 EXPECT_STR_EQ("ab ", textfield_
->GetSelectedText());
2329 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2330 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2332 SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
, "other");
2333 textfield_
->SelectAll(false);
2334 EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2335 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2339 // Long_Press gesture in Textfield can initiate a drag and drop now.
2340 TEST_F(TextfieldTest
, TestLongPressInitiatesDragDrop
) {
2342 textfield_
->SetText(ASCIIToUTF16("Hello string world"));
2344 // Ensure the textfield will provide selected text for drag data.
2345 textfield_
->SelectRange(gfx::Range(6, 12));
2346 const gfx::Point
kStringPoint(GetCursorPositionX(9), 0);
2348 // Enable touch-drag-drop to make long press effective.
2349 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2350 switches::kEnableTouchDragDrop
);
2352 // Create a long press event in the selected region should start a drag.
2353 GestureEventForTest
long_press(
2356 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2357 textfield_
->OnGestureEvent(&long_press
);
2358 EXPECT_TRUE(textfield_
->CanStartDragForView(NULL
, kStringPoint
,
2362 TEST_F(TextfieldTest
, GetTextfieldBaseline_FontFallbackTest
) {
2364 textfield_
->SetText(UTF8ToUTF16("abc"));
2365 const int old_baseline
= textfield_
->GetBaseline();
2367 // Set text which may fall back to a font which has taller baseline than
2368 // the default font.
2369 textfield_
->SetText(UTF8ToUTF16("\xE0\xB9\x91"));
2370 const int new_baseline
= textfield_
->GetBaseline();
2372 // Regardless of the text, the baseline must be the same.
2373 EXPECT_EQ(new_baseline
, old_baseline
);
2376 // Tests that a textfield view can be destroyed from OnKeyEvent() on its
2377 // controller and it does not crash.
2378 TEST_F(TextfieldTest
, DestroyingTextfieldFromOnKeyEvent
) {
2381 // The controller assumes ownership of the textfield.
2382 TextfieldDestroyerController
controller(textfield_
);
2383 EXPECT_TRUE(controller
.target());
2385 // Send a key to trigger OnKeyEvent().
2386 SendKeyEvent(ui::VKEY_RETURN
);
2388 EXPECT_FALSE(controller
.target());
2391 class TextfieldTouchSelectionTest
: public TextfieldTest
{
2394 void SetUp() override
{
2395 TextfieldTest::SetUp();
2396 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2397 switches::kEnableTouchEditing
);
2401 // Simulates a complete tap.
2402 void Tap(const gfx::Point
& point
) {
2403 GestureEventForTest
begin(
2404 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_BEGIN
));
2405 textfield_
->OnGestureEvent(&begin
);
2407 GestureEventForTest
tap_down(
2408 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN
));
2409 textfield_
->OnGestureEvent(&tap_down
);
2411 GestureEventForTest
show_press(
2414 ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS
));
2415 textfield_
->OnGestureEvent(&show_press
);
2417 ui::GestureEventDetails
tap_details(ui::ET_GESTURE_TAP
);
2418 tap_details
.set_tap_count(1);
2419 GestureEventForTest
tap(point
.x(), point
.y(), tap_details
);
2420 textfield_
->OnGestureEvent(&tap
);
2422 GestureEventForTest
end(
2423 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_END
));
2424 textfield_
->OnGestureEvent(&end
);
2429 // Touch selection and dragging currently only works for chromeos.
2430 #if defined(OS_CHROMEOS)
2431 TEST_F(TextfieldTouchSelectionTest
, TouchSelectionAndDraggingTest
) {
2433 textfield_
->SetText(ASCIIToUTF16("hello world"));
2434 EXPECT_FALSE(test_api_
->touch_selection_controller());
2435 const int x
= GetCursorPositionX(2);
2437 // Tapping on the textfield should turn on the TouchSelectionController.
2438 ui::GestureEventDetails
tap_details(ui::ET_GESTURE_TAP
);
2439 tap_details
.set_tap_count(1);
2440 GestureEventForTest
tap(x
, 0, tap_details
);
2441 textfield_
->OnGestureEvent(&tap
);
2442 EXPECT_TRUE(test_api_
->touch_selection_controller());
2444 // Un-focusing the textfield should reset the TouchSelectionController
2445 textfield_
->GetFocusManager()->ClearFocus();
2446 EXPECT_FALSE(test_api_
->touch_selection_controller());
2447 textfield_
->RequestFocus();
2449 // With touch editing enabled, long press should not show context menu.
2450 // Instead, select word and invoke TouchSelectionController.
2451 GestureEventForTest
long_press_1(
2452 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2453 textfield_
->OnGestureEvent(&long_press_1
);
2454 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2455 EXPECT_TRUE(test_api_
->touch_selection_controller());
2456 EXPECT_TRUE(long_press_1
.handled());
2458 // With touch drag drop enabled, long pressing in the selected region should
2459 // start a drag and remove TouchSelectionController.
2460 ASSERT_TRUE(switches::IsTouchDragDropEnabled());
2461 GestureEventForTest
long_press_2(
2462 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2463 textfield_
->OnGestureEvent(&long_press_2
);
2464 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2465 EXPECT_FALSE(test_api_
->touch_selection_controller());
2466 EXPECT_FALSE(long_press_2
.handled());
2468 // After disabling touch drag drop, long pressing again in the selection
2469 // region should not do anything.
2470 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2471 switches::kDisableTouchDragDrop
);
2472 ASSERT_FALSE(switches::IsTouchDragDropEnabled());
2473 GestureEventForTest
long_press_3(
2474 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2475 textfield_
->OnGestureEvent(&long_press_3
);
2476 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2477 EXPECT_FALSE(test_api_
->touch_selection_controller());
2478 EXPECT_FALSE(long_press_3
.handled());
2482 TEST_F(TextfieldTouchSelectionTest
, TouchSelectionInUnfocusableTextfield
) {
2484 textfield_
->SetText(ASCIIToUTF16("hello world"));
2485 gfx::Point
touch_point(GetCursorPositionX(2), 0);
2487 // Disable textfield and tap on it. Touch text selection should not get
2489 textfield_
->SetEnabled(false);
2491 EXPECT_FALSE(test_api_
->touch_selection_controller());
2492 textfield_
->SetEnabled(true);
2494 // Make textfield unfocusable and tap on it. Touch text selection should not
2496 textfield_
->SetFocusable(false);
2498 EXPECT_FALSE(textfield_
->HasFocus());
2499 EXPECT_FALSE(test_api_
->touch_selection_controller());
2500 textfield_
->SetFocusable(true);
2503 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
2504 #if defined(OS_MACOSX) && !defined(USE_AURA)
2505 #define MAYBE_TapOnSelection DISABLED_TapOnSelection
2507 #define MAYBE_TapOnSelection TapOnSelection
2510 TEST_F(TextfieldTouchSelectionTest
, MAYBE_TapOnSelection
) {
2512 textfield_
->SetText(ASCIIToUTF16("hello world"));
2513 gfx::Range
sel_range(2, 7);
2514 gfx::Range
tap_range(5, 5);
2515 gfx::Rect tap_rect
=
2516 GetCursorBounds(gfx::SelectionModel(tap_range
, gfx::CURSOR_FORWARD
));
2517 gfx::Point tap_point
= tap_rect
.CenterPoint();
2519 // Select range |sel_range| and check if touch selection handles are not
2520 // present and correct range is selected.
2521 textfield_
->SetSelectionRange(sel_range
);
2523 textfield_
->GetSelectionRange(&range
);
2524 EXPECT_FALSE(test_api_
->touch_selection_controller());
2525 EXPECT_EQ(sel_range
, range
);
2527 // Tap on selection and check if touch selectoin handles are shown, but
2528 // selection range is not modified.
2530 textfield_
->GetSelectionRange(&range
);
2531 EXPECT_TRUE(test_api_
->touch_selection_controller());
2532 EXPECT_EQ(sel_range
, range
);
2534 // Tap again on selection and check if touch selection handles are still
2535 // present and selection is changed to a cursor at tap location.
2537 textfield_
->GetSelectionRange(&range
);
2538 EXPECT_TRUE(test_api_
->touch_selection_controller());
2539 EXPECT_EQ(tap_range
, range
);
2542 TEST_F(TextfieldTest
, AccessiblePasswordTest
) {
2544 textfield_
->SetText(ASCIIToUTF16("password"));
2546 ui::AXViewState state_regular
;
2547 textfield_
->GetAccessibleState(&state_regular
);
2548 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD
, state_regular
.role
);
2549 EXPECT_EQ(ASCIIToUTF16("password"), state_regular
.value
);
2550 EXPECT_FALSE(state_regular
.HasStateFlag(ui::AX_STATE_PROTECTED
));
2552 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
2553 ui::AXViewState state_protected
;
2554 textfield_
->GetAccessibleState(&state_protected
);
2555 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD
, state_protected
.role
);
2556 EXPECT_EQ(ASCIIToUTF16("********"), state_protected
.value
);
2557 EXPECT_TRUE(state_protected
.HasStateFlag(ui::AX_STATE_PROTECTED
));
2560 } // namespace views