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/text_input_client.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/ui_base_switches.h"
22 #include "ui/base/ui_base_switches_util.h"
23 #include "ui/events/event.h"
24 #include "ui/events/event_utils.h"
25 #include "ui/events/keycodes/keyboard_codes.h"
26 #include "ui/events/test/event_generator.h"
27 #include "ui/gfx/render_text.h"
28 #include "ui/strings/grit/ui_strings.h"
29 #include "ui/views/controls/textfield/textfield_controller.h"
30 #include "ui/views/controls/textfield/textfield_model.h"
31 #include "ui/views/controls/textfield/textfield_test_api.h"
32 #include "ui/views/focus/focus_manager.h"
33 #include "ui/views/ime/mock_input_method.h"
34 #include "ui/views/test/test_views_delegate.h"
35 #include "ui/views/test/views_test_base.h"
36 #include "ui/views/test/widget_test.h"
37 #include "ui/views/widget/widget.h"
41 #include "base/win/windows_version.h"
44 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
45 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
49 #include "ui/events/event_utils.h"
52 using base::ASCIIToUTF16
;
53 using base::UTF8ToUTF16
;
54 using base::WideToUTF16
;
56 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
60 const base::char16 kHebrewLetterSamekh
= 0x05E1;
62 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
63 class TestTextfield
: public views::Textfield
{
69 weak_ptr_factory_(this) {}
71 bool OnKeyPressed(const ui::KeyEvent
& e
) override
{
74 // Since OnKeyPressed() might destroy |this|, get a weak pointer and
75 // verify it isn't null before writing the bool value to key_handled_.
76 base::WeakPtr
<TestTextfield
> textfield(weak_ptr_factory_
.GetWeakPtr());
77 bool key
= views::Textfield::OnKeyPressed(e
);
87 bool OnKeyReleased(const ui::KeyEvent
& e
) override
{
89 key_handled_
= views::Textfield::OnKeyReleased(e
);
90 EXPECT_FALSE(key_handled_
); // Textfield doesn't override OnKeyReleased.
94 // ui::TextInputClient overrides:
95 void InsertChar(base::char16 ch
, int flags
) override
{
96 views::Textfield::InsertChar(ch
, flags
);
97 #if defined(OS_MACOSX)
98 // On Mac, characters are inserted directly rather than attempting to get a
99 // unicode character from the ui::KeyEvent (which isn't always possible).
100 key_received_
= true;
104 bool key_handled() const { return key_handled_
; }
105 bool key_received() const { return key_received_
; }
107 void clear() { key_received_
= key_handled_
= false; }
113 base::WeakPtrFactory
<TestTextfield
> weak_ptr_factory_
;
115 DISALLOW_COPY_AND_ASSIGN(TestTextfield
);
118 // Convenience to make constructing a GestureEvent simpler.
119 class GestureEventForTest
: public ui::GestureEvent
{
121 GestureEventForTest(int x
, int y
, ui::GestureEventDetails details
)
122 : GestureEvent(x
, y
, 0, base::TimeDelta(), details
) {}
125 DISALLOW_COPY_AND_ASSIGN(GestureEventForTest
);
128 // This controller will happily destroy the target textfield passed on
129 // construction when a key event is triggered.
130 class TextfieldDestroyerController
: public views::TextfieldController
{
132 explicit TextfieldDestroyerController(views::Textfield
* target
)
134 target_
->set_controller(this);
137 views::Textfield
* target() { return target_
.get(); }
139 // views::TextfieldController:
140 bool HandleKeyEvent(views::Textfield
* sender
,
141 const ui::KeyEvent
& key_event
) override
{
147 scoped_ptr
<views::Textfield
> target_
;
150 base::string16
GetClipboardText(ui::ClipboardType type
) {
152 ui::Clipboard::GetForCurrentThread()->ReadText(type
, &text
);
156 void SetClipboardText(ui::ClipboardType type
, const std::string
& text
) {
157 ui::ScopedClipboardWriter(type
).WriteText(ASCIIToUTF16(text
));
164 class TextfieldTest
: public ViewsTestBase
, public TextfieldController
{
171 on_before_user_action_(0),
172 on_after_user_action_(0),
173 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST
) {
177 void TearDown() override
{
180 ViewsTestBase::TearDown();
183 ui::ClipboardType
GetAndResetCopiedToClipboard() {
184 ui::ClipboardType clipboard_type
= copied_to_clipboard_
;
185 copied_to_clipboard_
= ui::CLIPBOARD_TYPE_LAST
;
186 return clipboard_type
;
189 // TextfieldController:
190 void ContentsChanged(Textfield
* sender
,
191 const base::string16
& new_contents
) override
{
192 // Paste calls TextfieldController::ContentsChanged() explicitly even if the
193 // paste action did not change the content. So |new_contents| may match
194 // |last_contents_|. For more info, see http://crbug.com/79002
195 last_contents_
= new_contents
;
198 void OnBeforeUserAction(Textfield
* sender
) override
{
199 ++on_before_user_action_
;
202 void OnAfterUserAction(Textfield
* sender
) override
{
203 ++on_after_user_action_
;
206 void OnAfterCutOrCopy(ui::ClipboardType clipboard_type
) override
{
207 copied_to_clipboard_
= clipboard_type
;
210 void InitTextfield() {
214 void InitTextfields(int count
) {
215 ASSERT_FALSE(textfield_
);
216 textfield_
= new TestTextfield();
217 textfield_
->set_controller(this);
218 widget_
= new Widget();
220 // The widget type must be an activatable type, and we don't want to worry
221 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS.
222 Widget::InitParams params
=
223 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
225 params
.bounds
= gfx::Rect(100, 100, 100, 100);
226 widget_
->Init(params
);
227 View
* container
= new View();
228 widget_
->SetContentsView(container
);
229 container
->AddChildView(textfield_
);
230 textfield_
->SetBoundsRect(params
.bounds
);
231 textfield_
->set_id(1);
232 test_api_
.reset(new TextfieldTestApi(textfield_
));
234 for (int i
= 1; i
< count
; i
++) {
235 Textfield
* textfield
= new Textfield();
236 container
->AddChildView(textfield
);
237 textfield
->set_id(i
+ 1);
240 model_
= test_api_
->model();
241 model_
->ClearEditHistory();
243 input_method_
= new MockInputMethod();
244 widget_
->ReplaceInputMethod(input_method_
);
246 // Since the window type is activatable, showing the widget will also
247 // activate it. Calling Activate directly is insufficient, since that does
248 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the
249 // widget and the textfield must have focus to properly handle input.
251 textfield_
->RequestFocus();
253 // On Mac, activation is asynchronous since desktop widgets are used. We
254 // don't want parallel tests to steal active status either, so fake it.
255 #if defined(OS_MACOSX) && !defined(USE_AURA)
256 fake_activation_
= test::WidgetTest::FakeWidgetIsActiveAlways();
259 event_generator_
.reset(
260 new ui::test::EventGenerator(GetContext(), widget_
->GetNativeWindow()));
263 ui::MenuModel
* GetContextMenuModel() {
264 test_api_
->UpdateContextMenu();
265 return test_api_
->context_menu_contents();
268 // True if native Mac keystrokes should be used (to avoid ifdef litter).
269 bool TestingNativeMac() {
270 #if defined(OS_MACOSX)
278 void SendKeyEvent(ui::KeyboardCode key_code
,
281 bool control_or_command
,
283 bool control
= control_or_command
;
284 bool command
= false;
286 // By default, swap control and command for native events on Mac. This
287 // handles most cases.
288 if (TestingNativeMac())
289 std::swap(control
, command
);
291 int flags
= (alt
? ui::EF_ALT_DOWN
: 0) | (shift
? ui::EF_SHIFT_DOWN
: 0) |
292 (control
? ui::EF_CONTROL_DOWN
: 0) |
293 (command
? ui::EF_COMMAND_DOWN
: 0) |
294 (caps_lock
? ui::EF_CAPS_LOCK_DOWN
: 0);
296 event_generator_
->PressKey(key_code
, flags
);
299 void SendKeyEvent(ui::KeyboardCode key_code
,
301 bool control_or_command
) {
302 SendKeyEvent(key_code
, false, shift
, control_or_command
, false);
305 void SendKeyEvent(ui::KeyboardCode key_code
) {
306 SendKeyEvent(key_code
, false, false);
309 void SendKeyEvent(base::char16 ch
) {
311 ui::KeyboardCode code
=
312 ch
== ' ' ? ui::VKEY_SPACE
:
313 static_cast<ui::KeyboardCode
>(ui::VKEY_A
+ ch
- 'a');
316 // For unicode characters, assume they come from IME rather than the
317 // keyboard. So they are dispatched directly to the input method.
318 ui::KeyEvent
event(ch
, ui::VKEY_UNKNOWN
, ui::EF_NONE
);
319 input_method_
->DispatchKeyEvent(event
);
323 // Sends a platform-specific move (and select) to start of line.
324 void SendHomeEvent(bool shift
) {
325 if (TestingNativeMac()) {
326 // Use Cmd+Left on native Mac. An RTL-agnostic "end" doesn't have a
327 // default key-binding on Mac.
328 SendKeyEvent(ui::VKEY_LEFT
, shift
/* shift */, true /* command */);
331 SendKeyEvent(ui::VKEY_HOME
, shift
/* shift */, false /* control */);
334 // Sends a platform-specific move (and select) to end of line.
335 void SendEndEvent(bool shift
) {
336 if (TestingNativeMac()) {
337 SendKeyEvent(ui::VKEY_RIGHT
, shift
, true); // Cmd+Right.
340 SendKeyEvent(ui::VKEY_END
, shift
, false);
343 // Sends {delete, move, select} word {forward, backward}.
344 void SendWordEvent(ui::KeyboardCode key
, bool shift
) {
348 if (TestingNativeMac()) {
349 // Use Alt+Left/Right/Backspace on native Mac.
353 SendKeyEvent(key
, alt
, shift
, control
, caps
);
356 // Sends Shift+Delete if supported, otherwise Cmd+X again.
357 void SendAlternateCut() {
358 if (TestingNativeMac())
359 SendKeyEvent(ui::VKEY_X
, false, true);
361 SendKeyEvent(ui::VKEY_DELETE
, true, false);
364 // Sends Ctrl+Insert if supported, otherwise Cmd+C again.
365 void SendAlternateCopy() {
366 if (TestingNativeMac())
367 SendKeyEvent(ui::VKEY_C
, false, true);
369 SendKeyEvent(ui::VKEY_INSERT
, false, true);
372 // Sends Shift+Insert if supported, otherwise Cmd+V again.
373 void SendAlternatePaste() {
374 if (TestingNativeMac())
375 SendKeyEvent(ui::VKEY_V
, false, true);
377 SendKeyEvent(ui::VKEY_INSERT
, true, false);
380 View
* GetFocusedView() {
381 return widget_
->GetFocusManager()->GetFocusedView();
384 int GetCursorPositionX(int cursor_pos
) {
385 return test_api_
->GetRenderText()->GetCursorBounds(
386 gfx::SelectionModel(cursor_pos
, gfx::CURSOR_FORWARD
), false).x();
389 // Get the current cursor bounds.
390 gfx::Rect
GetCursorBounds() {
391 return test_api_
->GetRenderText()->GetUpdatedCursorBounds();
394 // Get the cursor bounds of |sel|.
395 gfx::Rect
GetCursorBounds(const gfx::SelectionModel
& sel
) {
396 return test_api_
->GetRenderText()->GetCursorBounds(sel
, true);
399 gfx::Rect
GetDisplayRect() {
400 return test_api_
->GetRenderText()->display_rect();
403 // Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and
404 // y-axis is in the middle of |bound|'s vertical range.
405 void MouseClick(const gfx::Rect bound
, int x_offset
) {
406 gfx::Point
point(bound
.x() + x_offset
, bound
.y() + bound
.height() / 2);
407 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, point
, point
,
408 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
409 ui::EF_LEFT_MOUSE_BUTTON
);
410 textfield_
->OnMousePressed(click
);
411 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, point
, point
,
412 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
413 ui::EF_LEFT_MOUSE_BUTTON
);
414 textfield_
->OnMouseReleased(release
);
417 // This is to avoid double/triple click.
418 void NonClientMouseClick() {
419 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
420 ui::EventTimeForNow(),
421 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_NON_CLIENT
,
422 ui::EF_LEFT_MOUSE_BUTTON
);
423 textfield_
->OnMousePressed(click
);
424 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, gfx::Point(), gfx::Point(),
425 ui::EventTimeForNow(),
426 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_NON_CLIENT
,
427 ui::EF_LEFT_MOUSE_BUTTON
);
428 textfield_
->OnMouseReleased(release
);
431 void VerifyTextfieldContextMenuContents(bool textfield_has_selection
,
433 ui::MenuModel
* menu
) {
434 EXPECT_EQ(can_undo
, menu
->IsEnabledAt(0 /* UNDO */));
435 EXPECT_TRUE(menu
->IsEnabledAt(1 /* Separator */));
436 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(2 /* CUT */));
437 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(3 /* COPY */));
438 EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
).empty(),
439 menu
->IsEnabledAt(4 /* PASTE */));
440 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(5 /* DELETE */));
441 EXPECT_TRUE(menu
->IsEnabledAt(6 /* Separator */));
442 EXPECT_TRUE(menu
->IsEnabledAt(7 /* SELECT ALL */));
445 // We need widget to populate wrapper class.
448 TestTextfield
* textfield_
;
449 scoped_ptr
<TextfieldTestApi
> test_api_
;
450 TextfieldModel
* model_
;
452 // The string from Controller::ContentsChanged callback.
453 base::string16 last_contents_
;
455 // For testing input method related behaviors.
456 MockInputMethod
* input_method_
;
458 // Indicates how many times OnBeforeUserAction() is called.
459 int on_before_user_action_
;
461 // Indicates how many times OnAfterUserAction() is called.
462 int on_after_user_action_
;
465 ui::ClipboardType copied_to_clipboard_
;
466 scoped_ptr
<test::WidgetTest::FakeActivation
> fake_activation_
;
467 scoped_ptr
<ui::test::EventGenerator
> event_generator_
;
469 DISALLOW_COPY_AND_ASSIGN(TextfieldTest
);
472 TEST_F(TextfieldTest
, ModelChangesTest
) {
475 // TextfieldController::ContentsChanged() shouldn't be called when changing
476 // text programmatically.
477 last_contents_
.clear();
478 textfield_
->SetText(ASCIIToUTF16("this is"));
480 EXPECT_STR_EQ("this is", model_
->text());
481 EXPECT_STR_EQ("this is", textfield_
->text());
482 EXPECT_TRUE(last_contents_
.empty());
484 textfield_
->AppendText(ASCIIToUTF16(" a test"));
485 EXPECT_STR_EQ("this is a test", model_
->text());
486 EXPECT_STR_EQ("this is a test", textfield_
->text());
487 EXPECT_TRUE(last_contents_
.empty());
489 EXPECT_EQ(base::string16(), textfield_
->GetSelectedText());
490 textfield_
->SelectAll(false);
491 EXPECT_STR_EQ("this is a test", textfield_
->GetSelectedText());
492 EXPECT_TRUE(last_contents_
.empty());
495 TEST_F(TextfieldTest
, KeyTest
) {
497 // Event flags: key, alt, shift, ctrl, caps-lock.
498 SendKeyEvent(ui::VKEY_T
, false, true, false, false);
499 SendKeyEvent(ui::VKEY_E
, false, false, false, false);
500 SendKeyEvent(ui::VKEY_X
, false, true, false, true);
501 SendKeyEvent(ui::VKEY_T
, false, false, false, true);
502 SendKeyEvent(ui::VKEY_1
, false, true, false, false);
503 SendKeyEvent(ui::VKEY_1
, false, false, false, false);
504 SendKeyEvent(ui::VKEY_1
, false, true, false, true);
505 SendKeyEvent(ui::VKEY_1
, false, false, false, true);
507 // On Mac, Caps+Shift remains uppercase.
508 if (TestingNativeMac())
509 EXPECT_STR_EQ("TeXT!1!1", textfield_
->text());
511 EXPECT_STR_EQ("TexT!1!1", textfield_
->text());
514 TEST_F(TextfieldTest
, ControlAndSelectTest
) {
515 // Insert a test string in a textfield.
517 textfield_
->SetText(ASCIIToUTF16("one two three"));
518 SendHomeEvent(false);
519 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
520 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
521 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
523 EXPECT_STR_EQ("one", textfield_
->GetSelectedText());
526 SendWordEvent(ui::VKEY_RIGHT
, true);
527 EXPECT_STR_EQ("one two", textfield_
->GetSelectedText());
528 SendWordEvent(ui::VKEY_RIGHT
, true);
529 EXPECT_STR_EQ("one two three", textfield_
->GetSelectedText());
530 SendWordEvent(ui::VKEY_LEFT
, true);
531 EXPECT_STR_EQ("one two ", textfield_
->GetSelectedText());
532 SendWordEvent(ui::VKEY_LEFT
, true);
533 EXPECT_STR_EQ("one ", textfield_
->GetSelectedText());
535 // Replace the selected text.
536 SendKeyEvent(ui::VKEY_Z
, true, false);
537 SendKeyEvent(ui::VKEY_E
, true, false);
538 SendKeyEvent(ui::VKEY_R
, true, false);
539 SendKeyEvent(ui::VKEY_O
, true, false);
540 SendKeyEvent(ui::VKEY_SPACE
, false, false);
541 EXPECT_STR_EQ("ZERO two three", textfield_
->text());
544 EXPECT_STR_EQ("two three", textfield_
->GetSelectedText());
546 EXPECT_STR_EQ("ZERO ", textfield_
->GetSelectedText());
549 TEST_F(TextfieldTest
, InsertionDeletionTest
) {
550 // Insert a test string in a textfield.
552 for (size_t i
= 0; i
< 10; i
++)
553 SendKeyEvent(static_cast<ui::KeyboardCode
>(ui::VKEY_A
+ i
));
554 EXPECT_STR_EQ("abcdefghij", textfield_
->text());
556 // Test the delete and backspace keys.
557 textfield_
->SelectRange(gfx::Range(5));
558 for (int i
= 0; i
< 3; i
++)
559 SendKeyEvent(ui::VKEY_BACK
);
560 EXPECT_STR_EQ("abfghij", textfield_
->text());
561 for (int i
= 0; i
< 3; i
++)
562 SendKeyEvent(ui::VKEY_DELETE
);
563 EXPECT_STR_EQ("abij", textfield_
->text());
565 // Select all and replace with "k".
566 textfield_
->SelectAll(false);
567 SendKeyEvent(ui::VKEY_K
);
568 EXPECT_STR_EQ("k", textfield_
->text());
570 // Delete the previous word from cursor.
572 textfield_
->SetText(ASCIIToUTF16("one two three four"));
574 SendWordEvent(ui::VKEY_BACK
, shift
);
575 EXPECT_STR_EQ("one two three ", textfield_
->text());
577 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
579 SendWordEvent(ui::VKEY_LEFT
, shift
);
581 SendWordEvent(ui::VKEY_BACK
, shift
);
582 #if defined(OS_LINUX)
583 EXPECT_STR_EQ("three ", textfield_
->text());
585 EXPECT_STR_EQ("one three ", textfield_
->text());
588 // Delete the next word from cursor.
589 textfield_
->SetText(ASCIIToUTF16("one two three four"));
591 SendHomeEvent(shift
);
592 SendWordEvent(ui::VKEY_DELETE
, shift
);
593 EXPECT_STR_EQ(" two three four", textfield_
->text());
595 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
597 SendWordEvent(ui::VKEY_RIGHT
, shift
);
599 SendWordEvent(ui::VKEY_DELETE
, shift
);
600 #if defined(OS_LINUX)
601 EXPECT_STR_EQ(" two", textfield_
->text());
603 EXPECT_STR_EQ(" two four", textfield_
->text());
607 TEST_F(TextfieldTest
, PasswordTest
) {
609 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
610 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
611 EXPECT_TRUE(textfield_
->enabled());
612 EXPECT_TRUE(textfield_
->IsFocusable());
614 last_contents_
.clear();
615 textfield_
->SetText(ASCIIToUTF16("password"));
616 // Ensure text() and the callback returns the actual text instead of "*".
617 EXPECT_STR_EQ("password", textfield_
->text());
618 EXPECT_TRUE(last_contents_
.empty());
619 model_
->SelectAll(false);
620 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "foo");
622 // Cut and copy should be disabled.
623 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
624 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
625 SendKeyEvent(ui::VKEY_X
, false, true);
626 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
627 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
628 SendKeyEvent(ui::VKEY_C
, false, true);
630 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
631 EXPECT_STR_EQ("password", textfield_
->text());
632 // [Shift]+[Delete] should just delete without copying text to the clipboard.
633 textfield_
->SelectAll(false);
634 SendKeyEvent(ui::VKEY_DELETE
, true, false);
636 // Paste should work normally.
637 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
638 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
639 SendKeyEvent(ui::VKEY_V
, false, true);
640 SendAlternatePaste();
641 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
642 EXPECT_STR_EQ("foofoofoo", textfield_
->text());
645 TEST_F(TextfieldTest
, TextInputType
) {
649 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT
, textfield_
->GetTextInputType());
652 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_URL
);
653 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL
, textfield_
->GetTextInputType());
654 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
655 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
657 // Readonly textfields have type NONE
658 textfield_
->SetReadOnly(true);
659 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, textfield_
->GetTextInputType());
661 textfield_
->SetReadOnly(false);
662 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
664 // As do disabled textfields
665 textfield_
->SetEnabled(false);
666 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, textfield_
->GetTextInputType());
668 textfield_
->SetEnabled(true);
669 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
672 TEST_F(TextfieldTest
, OnKeyPress
) {
675 // Character keys are handled by the input method.
676 SendKeyEvent(ui::VKEY_A
);
677 EXPECT_TRUE(textfield_
->key_received());
678 EXPECT_FALSE(textfield_
->key_handled());
681 // Arrow keys and home/end are handled by the textfield.
682 SendKeyEvent(ui::VKEY_LEFT
);
683 EXPECT_TRUE(textfield_
->key_received());
684 EXPECT_TRUE(textfield_
->key_handled());
687 SendKeyEvent(ui::VKEY_RIGHT
);
688 EXPECT_TRUE(textfield_
->key_received());
689 EXPECT_TRUE(textfield_
->key_handled());
692 const bool shift
= false;
693 SendHomeEvent(shift
);
694 EXPECT_TRUE(textfield_
->key_received());
695 EXPECT_TRUE(textfield_
->key_handled());
699 EXPECT_TRUE(textfield_
->key_received());
700 EXPECT_TRUE(textfield_
->key_handled());
703 // F20, up/down key won't be handled.
704 SendKeyEvent(ui::VKEY_F20
);
705 #if defined(OS_MACOSX)
706 // On Mac, key combinations that don't map to editing commands are forwarded
707 // on to the next responder, usually ending up at the window, which will beep.
708 EXPECT_FALSE(textfield_
->key_received());
710 EXPECT_TRUE(textfield_
->key_received());
712 EXPECT_FALSE(textfield_
->key_handled());
715 SendKeyEvent(ui::VKEY_UP
);
716 EXPECT_TRUE(textfield_
->key_received());
717 EXPECT_FALSE(textfield_
->key_handled());
720 SendKeyEvent(ui::VKEY_DOWN
);
721 EXPECT_TRUE(textfield_
->key_received());
722 EXPECT_FALSE(textfield_
->key_handled());
726 // Tests that default key bindings are handled even with a delegate installed.
727 TEST_F(TextfieldTest
, OnKeyPressBinding
) {
730 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
731 // Install a TextEditKeyBindingsDelegateAuraLinux that does nothing.
732 class TestDelegate
: public ui::TextEditKeyBindingsDelegateAuraLinux
{
735 ~TestDelegate() override
{}
738 const ui::Event
& event
,
739 std::vector
<ui::TextEditCommandAuraLinux
>* commands
) override
{
744 DISALLOW_COPY_AND_ASSIGN(TestDelegate
);
747 TestDelegate delegate
;
748 ui::SetTextEditKeyBindingsDelegate(&delegate
);
751 SendKeyEvent(ui::VKEY_A
, false, false);
752 EXPECT_STR_EQ("a", textfield_
->text());
755 // Undo/Redo command keys are handled by the textfield.
756 SendKeyEvent(ui::VKEY_Z
, false, true);
757 EXPECT_TRUE(textfield_
->key_received());
758 EXPECT_TRUE(textfield_
->key_handled());
759 EXPECT_TRUE(textfield_
->text().empty());
762 SendKeyEvent(ui::VKEY_Z
, true, true);
763 EXPECT_TRUE(textfield_
->key_received());
764 EXPECT_TRUE(textfield_
->key_handled());
765 EXPECT_STR_EQ("a", textfield_
->text());
768 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
769 ui::SetTextEditKeyBindingsDelegate(NULL
);
773 TEST_F(TextfieldTest
, CursorMovement
) {
776 // Test with trailing whitespace.
777 textfield_
->SetText(ASCIIToUTF16("one two hre "));
779 // Send the cursor at the end.
780 SendKeyEvent(ui::VKEY_END
);
782 // Ctrl+Left should move the cursor just before the last word.
783 const bool shift
= false;
784 SendWordEvent(ui::VKEY_LEFT
, shift
);
785 SendKeyEvent(ui::VKEY_T
);
786 EXPECT_STR_EQ("one two thre ", textfield_
->text());
787 EXPECT_STR_EQ("one two thre ", last_contents_
);
789 // Ctrl+Right should move the cursor to the end of the last word.
790 SendWordEvent(ui::VKEY_RIGHT
, shift
);
791 SendKeyEvent(ui::VKEY_E
);
792 EXPECT_STR_EQ("one two three ", textfield_
->text());
793 EXPECT_STR_EQ("one two three ", last_contents_
);
795 // Ctrl+Right again should move the cursor to the end.
796 SendWordEvent(ui::VKEY_RIGHT
, shift
);
797 SendKeyEvent(ui::VKEY_BACK
);
798 EXPECT_STR_EQ("one two three", textfield_
->text());
799 EXPECT_STR_EQ("one two three", last_contents_
);
801 // Test with leading whitespace.
802 textfield_
->SetText(ASCIIToUTF16(" ne two"));
804 // Send the cursor at the beginning.
805 SendHomeEvent(shift
);
807 // Ctrl+Right, then Ctrl+Left should move the cursor to the beginning of the
809 SendWordEvent(ui::VKEY_RIGHT
, shift
);
810 SendWordEvent(ui::VKEY_LEFT
, shift
);
811 SendKeyEvent(ui::VKEY_O
);
812 EXPECT_STR_EQ(" one two", textfield_
->text());
813 EXPECT_STR_EQ(" one two", last_contents_
);
815 // Ctrl+Left to move the cursor to the beginning of the first word.
816 SendWordEvent(ui::VKEY_LEFT
, shift
);
817 // Ctrl+Left again should move the cursor back to the very beginning.
818 SendWordEvent(ui::VKEY_LEFT
, shift
);
819 SendKeyEvent(ui::VKEY_DELETE
);
820 EXPECT_STR_EQ("one two", textfield_
->text());
821 EXPECT_STR_EQ("one two", last_contents_
);
824 TEST_F(TextfieldTest
, FocusTraversalTest
) {
826 textfield_
->RequestFocus();
828 EXPECT_EQ(1, GetFocusedView()->id());
829 widget_
->GetFocusManager()->AdvanceFocus(false);
830 EXPECT_EQ(2, GetFocusedView()->id());
831 widget_
->GetFocusManager()->AdvanceFocus(false);
832 EXPECT_EQ(3, GetFocusedView()->id());
833 // Cycle back to the first textfield.
834 widget_
->GetFocusManager()->AdvanceFocus(false);
835 EXPECT_EQ(1, GetFocusedView()->id());
837 widget_
->GetFocusManager()->AdvanceFocus(true);
838 EXPECT_EQ(3, GetFocusedView()->id());
839 widget_
->GetFocusManager()->AdvanceFocus(true);
840 EXPECT_EQ(2, GetFocusedView()->id());
841 widget_
->GetFocusManager()->AdvanceFocus(true);
842 EXPECT_EQ(1, GetFocusedView()->id());
843 // Cycle back to the last textfield.
844 widget_
->GetFocusManager()->AdvanceFocus(true);
845 EXPECT_EQ(3, GetFocusedView()->id());
847 // Request focus should still work.
848 textfield_
->RequestFocus();
849 EXPECT_EQ(1, GetFocusedView()->id());
851 // Test if clicking on textfield view sets the focus.
852 widget_
->GetFocusManager()->AdvanceFocus(true);
853 EXPECT_EQ(3, GetFocusedView()->id());
854 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
855 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
856 ui::EF_LEFT_MOUSE_BUTTON
);
857 textfield_
->OnMousePressed(click
);
858 EXPECT_EQ(1, GetFocusedView()->id());
860 // Tab/Shift+Tab should also cycle focus, not insert a tab character.
861 SendKeyEvent(ui::VKEY_TAB
, false, false);
862 EXPECT_EQ(2, GetFocusedView()->id());
863 SendKeyEvent(ui::VKEY_TAB
, false, false);
864 EXPECT_EQ(3, GetFocusedView()->id());
865 // Cycle back to the first textfield.
866 SendKeyEvent(ui::VKEY_TAB
, false, false);
867 EXPECT_EQ(1, GetFocusedView()->id());
869 SendKeyEvent(ui::VKEY_TAB
, true, false);
870 EXPECT_EQ(3, GetFocusedView()->id());
871 SendKeyEvent(ui::VKEY_TAB
, true, false);
872 EXPECT_EQ(2, GetFocusedView()->id());
873 SendKeyEvent(ui::VKEY_TAB
, true, false);
874 EXPECT_EQ(1, GetFocusedView()->id());
875 // Cycle back to the last textfield.
876 SendKeyEvent(ui::VKEY_TAB
, true, false);
877 EXPECT_EQ(3, GetFocusedView()->id());
880 TEST_F(TextfieldTest
, ContextMenuDisplayTest
) {
882 EXPECT_TRUE(textfield_
->context_menu_controller());
883 textfield_
->SetText(ASCIIToUTF16("hello world"));
884 ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE
);
885 textfield_
->ClearEditHistory();
886 EXPECT_TRUE(GetContextMenuModel());
887 VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
889 textfield_
->SelectAll(false);
890 VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel());
892 SendKeyEvent(ui::VKEY_T
);
893 VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel());
895 textfield_
->SelectAll(false);
896 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
898 // Exercise the "paste enabled?" check in the verifier.
899 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
900 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
903 TEST_F(TextfieldTest
, DoubleAndTripleClickTest
) {
905 textfield_
->SetText(ASCIIToUTF16("hello world"));
906 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
907 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
908 ui::EF_LEFT_MOUSE_BUTTON
);
909 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, gfx::Point(), gfx::Point(),
910 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
911 ui::EF_LEFT_MOUSE_BUTTON
);
912 ui::MouseEvent
double_click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
913 ui::EventTimeForNow(),
914 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_DOUBLE_CLICK
,
915 ui::EF_LEFT_MOUSE_BUTTON
);
917 // Test for double click.
918 textfield_
->OnMousePressed(click
);
919 textfield_
->OnMouseReleased(release
);
920 EXPECT_TRUE(textfield_
->GetSelectedText().empty());
921 textfield_
->OnMousePressed(double_click
);
922 textfield_
->OnMouseReleased(release
);
923 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
925 // Test for triple click.
926 textfield_
->OnMousePressed(click
);
927 textfield_
->OnMouseReleased(release
);
928 EXPECT_STR_EQ("hello world", textfield_
->GetSelectedText());
930 // Another click should reset back to double click.
931 textfield_
->OnMousePressed(click
);
932 textfield_
->OnMouseReleased(release
);
933 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
936 TEST_F(TextfieldTest
, DragToSelect
) {
938 textfield_
->SetText(ASCIIToUTF16("hello world"));
939 const int kStart
= GetCursorPositionX(5);
940 const int kEnd
= 500;
941 gfx::Point
start_point(kStart
, 0);
942 gfx::Point
end_point(kEnd
, 0);
943 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, start_point
, start_point
,
944 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
945 ui::EF_LEFT_MOUSE_BUTTON
);
946 ui::MouseEvent
click_b(ui::ET_MOUSE_PRESSED
, end_point
, end_point
,
947 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
948 ui::EF_LEFT_MOUSE_BUTTON
);
949 ui::MouseEvent
drag_left(ui::ET_MOUSE_DRAGGED
, gfx::Point(), gfx::Point(),
950 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
951 ui::MouseEvent
drag_right(ui::ET_MOUSE_DRAGGED
, end_point
, end_point
,
952 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
953 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, end_point
, end_point
,
954 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
955 ui::EF_LEFT_MOUSE_BUTTON
);
956 textfield_
->OnMousePressed(click_a
);
957 EXPECT_TRUE(textfield_
->GetSelectedText().empty());
958 // Check that dragging left selects the beginning of the string.
959 textfield_
->OnMouseDragged(drag_left
);
960 base::string16 text_left
= textfield_
->GetSelectedText();
961 EXPECT_STR_EQ("hello", text_left
);
962 // Check that dragging right selects the rest of the string.
963 textfield_
->OnMouseDragged(drag_right
);
964 base::string16 text_right
= textfield_
->GetSelectedText();
965 EXPECT_STR_EQ(" world", text_right
);
966 // Check that releasing in the same location does not alter the selection.
967 textfield_
->OnMouseReleased(release
);
968 EXPECT_EQ(text_right
, textfield_
->GetSelectedText());
969 // Check that dragging from beyond the text length works too.
970 textfield_
->OnMousePressed(click_b
);
971 textfield_
->OnMouseDragged(drag_left
);
972 textfield_
->OnMouseReleased(release
);
973 EXPECT_EQ(textfield_
->text(), textfield_
->GetSelectedText());
977 TEST_F(TextfieldTest
, DragAndDrop_AcceptDrop
) {
979 textfield_
->SetText(ASCIIToUTF16("hello world"));
981 ui::OSExchangeData data
;
982 base::string16
string(ASCIIToUTF16("string "));
983 data
.SetString(string
);
985 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
987 // Ensure that disabled textfields do not accept drops.
988 textfield_
->SetEnabled(false);
989 EXPECT_FALSE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
990 EXPECT_EQ(0, formats
);
991 EXPECT_TRUE(custom_formats
.empty());
992 EXPECT_FALSE(textfield_
->CanDrop(data
));
993 textfield_
->SetEnabled(true);
995 // Ensure that read-only textfields do not accept drops.
996 textfield_
->SetReadOnly(true);
997 EXPECT_FALSE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
998 EXPECT_EQ(0, formats
);
999 EXPECT_TRUE(custom_formats
.empty());
1000 EXPECT_FALSE(textfield_
->CanDrop(data
));
1001 textfield_
->SetReadOnly(false);
1003 // Ensure that enabled and editable textfields do accept drops.
1004 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1005 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1006 EXPECT_TRUE(custom_formats
.empty());
1007 EXPECT_TRUE(textfield_
->CanDrop(data
));
1008 gfx::Point
drop_point(GetCursorPositionX(6), 0);
1009 ui::DropTargetEvent
drop(data
, drop_point
, drop_point
,
1010 ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_MOVE
);
1011 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_MOVE
,
1012 textfield_
->OnDragUpdated(drop
));
1013 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
, textfield_
->OnPerformDrop(drop
));
1014 EXPECT_STR_EQ("hello string world", textfield_
->text());
1016 // Ensure that textfields do not accept non-OSExchangeData::STRING types.
1017 ui::OSExchangeData bad_data
;
1018 bad_data
.SetFilename(base::FilePath(FILE_PATH_LITERAL("x")));
1019 ui::OSExchangeData::CustomFormat fmt
= ui::Clipboard::GetBitmapFormatType();
1020 bad_data
.SetPickledData(fmt
, Pickle());
1021 bad_data
.SetFileContents(base::FilePath(L
"x"), "x");
1022 bad_data
.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org"));
1023 ui::OSExchangeData::DownloadFileInfo
download(base::FilePath(), NULL
);
1024 bad_data
.SetDownloadFileInfo(download
);
1025 EXPECT_FALSE(textfield_
->CanDrop(bad_data
));
1029 TEST_F(TextfieldTest
, DragAndDrop_InitiateDrag
) {
1031 textfield_
->SetText(ASCIIToUTF16("hello string world"));
1033 // Ensure the textfield will provide selected text for drag data.
1034 base::string16 string
;
1035 ui::OSExchangeData data
;
1036 const gfx::Range
kStringRange(6, 12);
1037 textfield_
->SelectRange(kStringRange
);
1038 const gfx::Point
kStringPoint(GetCursorPositionX(9), 0);
1039 textfield_
->WriteDragDataForView(NULL
, kStringPoint
, &data
);
1040 EXPECT_TRUE(data
.GetString(&string
));
1041 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1043 // Ensure that disabled textfields do not support drag operations.
1044 textfield_
->SetEnabled(false);
1045 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1046 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1047 textfield_
->SetEnabled(true);
1048 // Ensure that textfields without selections do not support drag operations.
1049 textfield_
->ClearSelection();
1050 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1051 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1052 textfield_
->SelectRange(kStringRange
);
1053 // Ensure that password textfields do not support drag operations.
1054 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
1055 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1056 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1057 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT
);
1058 // Ensure that textfields only initiate drag operations inside the selection.
1059 ui::MouseEvent
press_event(ui::ET_MOUSE_PRESSED
, kStringPoint
, kStringPoint
,
1060 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1061 ui::EF_LEFT_MOUSE_BUTTON
);
1062 textfield_
->OnMousePressed(press_event
);
1063 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1064 textfield_
->GetDragOperationsForView(NULL
, gfx::Point()));
1065 EXPECT_FALSE(textfield_
->CanStartDragForView(NULL
, gfx::Point(),
1067 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
,
1068 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1069 EXPECT_TRUE(textfield_
->CanStartDragForView(NULL
, kStringPoint
,
1071 // Ensure that textfields support local moves.
1072 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1073 textfield_
->GetDragOperationsForView(textfield_
, kStringPoint
));
1076 TEST_F(TextfieldTest
, DragAndDrop_ToTheRight
) {
1078 textfield_
->SetText(ASCIIToUTF16("hello world"));
1080 base::string16 string
;
1081 ui::OSExchangeData data
;
1084 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1086 // Start dragging "ello".
1087 textfield_
->SelectRange(gfx::Range(1, 5));
1088 gfx::Point
point(GetCursorPositionX(3), 0);
1089 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, point
, point
,
1090 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1091 ui::EF_LEFT_MOUSE_BUTTON
);
1092 textfield_
->OnMousePressed(click_a
);
1093 EXPECT_TRUE(textfield_
->CanStartDragForView(textfield_
, click_a
.location(),
1095 operations
= textfield_
->GetDragOperationsForView(textfield_
,
1096 click_a
.location());
1097 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1099 textfield_
->WriteDragDataForView(NULL
, click_a
.location(), &data
);
1100 EXPECT_TRUE(data
.GetString(&string
));
1101 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1102 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1103 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1104 EXPECT_TRUE(custom_formats
.empty());
1106 // Drop "ello" after "w".
1107 const gfx::Point
kDropPoint(GetCursorPositionX(7), 0);
1108 EXPECT_TRUE(textfield_
->CanDrop(data
));
1109 ui::DropTargetEvent
drop_a(data
, kDropPoint
, kDropPoint
, operations
);
1110 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop_a
));
1111 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnPerformDrop(drop_a
));
1112 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1113 textfield_
->OnDragDone();
1115 // Undo/Redo the drag&drop change.
1116 SendKeyEvent(ui::VKEY_Z
, false, true);
1117 EXPECT_STR_EQ("hello world", textfield_
->text());
1118 SendKeyEvent(ui::VKEY_Z
, false, true);
1119 EXPECT_STR_EQ("", textfield_
->text());
1120 SendKeyEvent(ui::VKEY_Z
, false, true);
1121 EXPECT_STR_EQ("", textfield_
->text());
1122 SendKeyEvent(ui::VKEY_Z
, true, true);
1123 EXPECT_STR_EQ("hello world", textfield_
->text());
1124 SendKeyEvent(ui::VKEY_Z
, true, true);
1125 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1126 SendKeyEvent(ui::VKEY_Z
, true, true);
1127 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1130 TEST_F(TextfieldTest
, DragAndDrop_ToTheLeft
) {
1132 textfield_
->SetText(ASCIIToUTF16("hello world"));
1134 base::string16 string
;
1135 ui::OSExchangeData data
;
1138 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1140 // Start dragging " worl".
1141 textfield_
->SelectRange(gfx::Range(5, 10));
1142 gfx::Point
point(GetCursorPositionX(7), 0);
1143 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, point
, point
,
1144 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1145 ui::EF_LEFT_MOUSE_BUTTON
);
1146 textfield_
->OnMousePressed(click_a
);
1147 EXPECT_TRUE(textfield_
->CanStartDragForView(textfield_
, click_a
.location(),
1149 operations
= textfield_
->GetDragOperationsForView(textfield_
,
1150 click_a
.location());
1151 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1153 textfield_
->WriteDragDataForView(NULL
, click_a
.location(), &data
);
1154 EXPECT_TRUE(data
.GetString(&string
));
1155 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1156 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1157 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1158 EXPECT_TRUE(custom_formats
.empty());
1160 // Drop " worl" after "h".
1161 EXPECT_TRUE(textfield_
->CanDrop(data
));
1162 gfx::Point
drop_point(GetCursorPositionX(1), 0);
1163 ui::DropTargetEvent
drop_a(data
, drop_point
, drop_point
, operations
);
1164 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop_a
));
1165 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnPerformDrop(drop_a
));
1166 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1167 textfield_
->OnDragDone();
1169 // Undo/Redo the drag&drop change.
1170 SendKeyEvent(ui::VKEY_Z
, false, true);
1171 EXPECT_STR_EQ("hello world", textfield_
->text());
1172 SendKeyEvent(ui::VKEY_Z
, false, true);
1173 EXPECT_STR_EQ("", textfield_
->text());
1174 SendKeyEvent(ui::VKEY_Z
, false, true);
1175 EXPECT_STR_EQ("", textfield_
->text());
1176 SendKeyEvent(ui::VKEY_Z
, true, true);
1177 EXPECT_STR_EQ("hello world", textfield_
->text());
1178 SendKeyEvent(ui::VKEY_Z
, true, true);
1179 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1180 SendKeyEvent(ui::VKEY_Z
, true, true);
1181 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1184 TEST_F(TextfieldTest
, DragAndDrop_Canceled
) {
1186 textfield_
->SetText(ASCIIToUTF16("hello world"));
1188 // Start dragging "worl".
1189 textfield_
->SelectRange(gfx::Range(6, 10));
1190 gfx::Point
point(GetCursorPositionX(8), 0);
1191 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, point
, point
,
1192 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1193 ui::EF_LEFT_MOUSE_BUTTON
);
1194 textfield_
->OnMousePressed(click
);
1195 ui::OSExchangeData data
;
1196 textfield_
->WriteDragDataForView(NULL
, click
.location(), &data
);
1197 EXPECT_TRUE(textfield_
->CanDrop(data
));
1198 // Drag the text over somewhere valid, outside the current selection.
1199 gfx::Point
drop_point(GetCursorPositionX(2), 0);
1200 ui::DropTargetEvent
drop(data
, drop_point
, drop_point
,
1201 ui::DragDropTypes::DRAG_MOVE
);
1202 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop
));
1203 // "Cancel" the drag, via move and release over the selection, and OnDragDone.
1204 gfx::Point
drag_point(GetCursorPositionX(9), 0);
1205 ui::MouseEvent
drag(ui::ET_MOUSE_DRAGGED
, drag_point
, drag_point
,
1206 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1207 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, drag_point
, drag_point
,
1208 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1209 ui::EF_LEFT_MOUSE_BUTTON
);
1210 textfield_
->OnMouseDragged(drag
);
1211 textfield_
->OnMouseReleased(release
);
1212 textfield_
->OnDragDone();
1213 EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_
->text());
1216 TEST_F(TextfieldTest
, ReadOnlyTest
) {
1218 textfield_
->SetText(ASCIIToUTF16("read only"));
1219 textfield_
->SetReadOnly(true);
1220 EXPECT_TRUE(textfield_
->enabled());
1221 EXPECT_TRUE(textfield_
->IsFocusable());
1224 SendHomeEvent(shift
);
1225 EXPECT_EQ(0U, textfield_
->GetCursorPosition());
1226 SendEndEvent(shift
);
1227 EXPECT_EQ(9U, textfield_
->GetCursorPosition());
1229 SendKeyEvent(ui::VKEY_LEFT
, shift
, false);
1230 EXPECT_EQ(8U, textfield_
->GetCursorPosition());
1231 SendWordEvent(ui::VKEY_LEFT
, shift
);
1232 EXPECT_EQ(5U, textfield_
->GetCursorPosition());
1234 SendWordEvent(ui::VKEY_LEFT
, shift
);
1235 EXPECT_EQ(0U, textfield_
->GetCursorPosition());
1236 EXPECT_STR_EQ("read ", textfield_
->GetSelectedText());
1237 textfield_
->SelectAll(false);
1238 EXPECT_STR_EQ("read only", textfield_
->GetSelectedText());
1240 // Cut should be disabled.
1241 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1242 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
1243 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
1244 SendKeyEvent(ui::VKEY_X
, false, true);
1246 EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1247 EXPECT_STR_EQ("read only", textfield_
->text());
1249 // Paste should be disabled.
1250 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
1251 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
1252 SendKeyEvent(ui::VKEY_V
, false, true);
1253 SendAlternatePaste();
1254 EXPECT_STR_EQ("read only", textfield_
->text());
1256 // Copy should work normally.
1257 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1258 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
1259 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
1260 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1261 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1262 SendKeyEvent(ui::VKEY_C
, false, true);
1263 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1264 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1265 SendAlternateCopy();
1266 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1268 // SetText should work even in read only mode.
1269 textfield_
->SetText(ASCIIToUTF16(" four five six "));
1270 EXPECT_STR_EQ(" four five six ", textfield_
->text());
1272 textfield_
->SelectAll(false);
1273 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1275 // Text field is unmodifiable and selection shouldn't change.
1276 SendKeyEvent(ui::VKEY_DELETE
);
1277 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1278 SendKeyEvent(ui::VKEY_BACK
);
1279 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1280 SendKeyEvent(ui::VKEY_T
);
1281 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1284 TEST_F(TextfieldTest
, TextInputClientTest
) {
1286 ui::TextInputClient
* client
= textfield_
->GetTextInputClient();
1287 EXPECT_TRUE(client
);
1288 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT
, client
->GetTextInputType());
1290 textfield_
->SetText(ASCIIToUTF16("0123456789"));
1292 EXPECT_TRUE(client
->GetTextRange(&range
));
1293 EXPECT_EQ(0U, range
.start());
1294 EXPECT_EQ(10U, range
.end());
1296 EXPECT_TRUE(client
->SetSelectionRange(gfx::Range(1, 4)));
1297 EXPECT_TRUE(client
->GetSelectionRange(&range
));
1298 EXPECT_EQ(gfx::Range(1, 4), range
);
1300 base::string16 substring
;
1301 EXPECT_TRUE(client
->GetTextFromRange(range
, &substring
));
1302 EXPECT_STR_EQ("123", substring
);
1304 EXPECT_TRUE(client
->DeleteRange(range
));
1305 EXPECT_STR_EQ("0456789", textfield_
->text());
1307 ui::CompositionText composition
;
1308 composition
.text
= UTF8ToUTF16("321");
1309 // Set composition through input method.
1310 input_method_
->Clear();
1311 input_method_
->SetCompositionTextForNextKey(composition
);
1312 textfield_
->clear();
1314 on_before_user_action_
= on_after_user_action_
= 0;
1316 // Send a key to trigger MockInputMethod::DispatchKeyEvent(). Note the
1317 // specific VKEY isn't used (MockInputMethod will mock a ui::VKEY_PROCESSKEY
1318 // whenever it has a test composition). However, on Mac, it can't be a letter
1319 // (e.g. VKEY_A) since all native character events on Mac are unicode events
1320 // and don't have a meaningful ui::KeyEvent that would trigger
1321 // DispatchKeyEvent().
1322 SendKeyEvent(ui::VKEY_RETURN
);
1324 EXPECT_TRUE(textfield_
->key_received());
1325 EXPECT_FALSE(textfield_
->key_handled());
1326 EXPECT_TRUE(client
->HasCompositionText());
1327 EXPECT_TRUE(client
->GetCompositionTextRange(&range
));
1328 EXPECT_STR_EQ("0321456789", textfield_
->text());
1329 EXPECT_EQ(gfx::Range(1, 4), range
);
1330 EXPECT_EQ(1, on_before_user_action_
);
1331 EXPECT_EQ(1, on_after_user_action_
);
1333 input_method_
->SetResultTextForNextKey(UTF8ToUTF16("123"));
1334 on_before_user_action_
= on_after_user_action_
= 0;
1335 textfield_
->clear();
1336 SendKeyEvent(ui::VKEY_RETURN
);
1337 EXPECT_TRUE(textfield_
->key_received());
1338 EXPECT_FALSE(textfield_
->key_handled());
1339 EXPECT_FALSE(client
->HasCompositionText());
1340 EXPECT_FALSE(input_method_
->cancel_composition_called());
1341 EXPECT_STR_EQ("0123456789", textfield_
->text());
1342 EXPECT_EQ(1, on_before_user_action_
);
1343 EXPECT_EQ(1, on_after_user_action_
);
1345 input_method_
->Clear();
1346 input_method_
->SetCompositionTextForNextKey(composition
);
1347 textfield_
->clear();
1348 SendKeyEvent(ui::VKEY_RETURN
);
1349 EXPECT_TRUE(client
->HasCompositionText());
1350 EXPECT_STR_EQ("0123321456789", textfield_
->text());
1352 on_before_user_action_
= on_after_user_action_
= 0;
1353 textfield_
->clear();
1354 SendKeyEvent(ui::VKEY_RIGHT
);
1355 EXPECT_FALSE(client
->HasCompositionText());
1356 EXPECT_TRUE(input_method_
->cancel_composition_called());
1357 EXPECT_TRUE(textfield_
->key_received());
1358 EXPECT_TRUE(textfield_
->key_handled());
1359 EXPECT_STR_EQ("0123321456789", textfield_
->text());
1360 EXPECT_EQ(8U, textfield_
->GetCursorPosition());
1361 EXPECT_EQ(1, on_before_user_action_
);
1362 EXPECT_EQ(1, on_after_user_action_
);
1364 textfield_
->clear();
1365 textfield_
->SetText(ASCIIToUTF16("0123456789"));
1366 EXPECT_TRUE(client
->SetSelectionRange(gfx::Range(5, 5)));
1367 client
->ExtendSelectionAndDelete(4, 2);
1368 EXPECT_STR_EQ("0789", textfield_
->text());
1370 // On{Before,After}UserAction should be called by whatever user action
1371 // triggers clearing or setting a selection if appropriate.
1372 on_before_user_action_
= on_after_user_action_
= 0;
1373 textfield_
->clear();
1374 textfield_
->ClearSelection();
1375 textfield_
->SelectAll(false);
1376 EXPECT_EQ(0, on_before_user_action_
);
1377 EXPECT_EQ(0, on_after_user_action_
);
1379 input_method_
->Clear();
1381 // Changing the Textfield to readonly shouldn't change the input client, since
1382 // it's still required for selections and clipboard copy.
1383 ui::TextInputClient
* text_input_client
= textfield_
->GetTextInputClient();
1384 EXPECT_TRUE(text_input_client
);
1385 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1386 textfield_
->SetReadOnly(true);
1387 EXPECT_TRUE(input_method_
->text_input_type_changed());
1388 EXPECT_EQ(text_input_client
, textfield_
->GetTextInputClient());
1389 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1391 input_method_
->Clear();
1392 textfield_
->SetReadOnly(false);
1393 EXPECT_TRUE(input_method_
->text_input_type_changed());
1394 EXPECT_EQ(text_input_client
, textfield_
->GetTextInputClient());
1395 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1397 input_method_
->Clear();
1398 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
1399 EXPECT_TRUE(input_method_
->text_input_type_changed());
1400 EXPECT_TRUE(textfield_
->GetTextInputClient());
1403 TEST_F(TextfieldTest
, UndoRedoTest
) {
1405 SendKeyEvent(ui::VKEY_A
);
1406 EXPECT_STR_EQ("a", textfield_
->text());
1407 SendKeyEvent(ui::VKEY_Z
, false, true);
1408 EXPECT_STR_EQ("", textfield_
->text());
1409 SendKeyEvent(ui::VKEY_Z
, false, true);
1410 EXPECT_STR_EQ("", textfield_
->text());
1411 SendKeyEvent(ui::VKEY_Z
, true, true);
1412 EXPECT_STR_EQ("a", textfield_
->text());
1413 SendKeyEvent(ui::VKEY_Z
, true, true);
1414 EXPECT_STR_EQ("a", textfield_
->text());
1417 textfield_
->AppendText(ASCIIToUTF16("b"));
1418 last_contents_
.clear(); // AppendText doesn't call ContentsChanged.
1419 EXPECT_STR_EQ("ab", textfield_
->text());
1420 SendKeyEvent(ui::VKEY_Z
, false, true);
1421 EXPECT_STR_EQ("a", textfield_
->text());
1422 SendKeyEvent(ui::VKEY_Z
, true, true);
1423 EXPECT_STR_EQ("ab", textfield_
->text());
1426 SendKeyEvent(ui::VKEY_C
);
1427 // Undo'ing append moves the cursor to the end for now.
1428 // A no-op SetText won't add a new edit; see TextfieldModel::SetText.
1429 EXPECT_STR_EQ("abc", textfield_
->text());
1430 textfield_
->SetText(ASCIIToUTF16("abc"));
1431 EXPECT_STR_EQ("abc", textfield_
->text());
1432 SendKeyEvent(ui::VKEY_Z
, false, true);
1433 EXPECT_STR_EQ("ab", textfield_
->text());
1434 SendKeyEvent(ui::VKEY_Z
, true, true);
1435 EXPECT_STR_EQ("abc", textfield_
->text());
1436 SendKeyEvent(ui::VKEY_Z
, true, true);
1437 EXPECT_STR_EQ("abc", textfield_
->text());
1438 textfield_
->SetText(ASCIIToUTF16("123"));
1439 textfield_
->SetText(ASCIIToUTF16("123"));
1440 EXPECT_STR_EQ("123", textfield_
->text());
1441 SendKeyEvent(ui::VKEY_END
, false, false);
1442 SendKeyEvent(ui::VKEY_4
, false, false);
1443 EXPECT_STR_EQ("1234", textfield_
->text());
1444 last_contents_
.clear();
1445 SendKeyEvent(ui::VKEY_Z
, false, true);
1446 EXPECT_STR_EQ("123", textfield_
->text());
1447 SendKeyEvent(ui::VKEY_Z
, false, true);
1448 // the insert edit "c" and set edit "123" are merged to single edit,
1449 // so text becomes "ab" after undo.
1450 EXPECT_STR_EQ("ab", textfield_
->text());
1451 SendKeyEvent(ui::VKEY_Z
, false, true);
1452 EXPECT_STR_EQ("a", textfield_
->text());
1453 SendKeyEvent(ui::VKEY_Z
, true, true);
1454 EXPECT_STR_EQ("ab", textfield_
->text());
1455 SendKeyEvent(ui::VKEY_Z
, true, true);
1456 EXPECT_STR_EQ("123", textfield_
->text());
1457 SendKeyEvent(ui::VKEY_Z
, true, true);
1458 EXPECT_STR_EQ("1234", textfield_
->text());
1460 // Undoing to the same text shouldn't call ContentsChanged.
1461 SendKeyEvent(ui::VKEY_A
, false, true); // select all
1462 SendKeyEvent(ui::VKEY_A
);
1463 EXPECT_STR_EQ("a", textfield_
->text());
1464 SendKeyEvent(ui::VKEY_B
);
1465 SendKeyEvent(ui::VKEY_C
);
1466 EXPECT_STR_EQ("abc", textfield_
->text());
1467 SendKeyEvent(ui::VKEY_Z
, false, true);
1468 EXPECT_STR_EQ("1234", textfield_
->text());
1469 SendKeyEvent(ui::VKEY_Z
, true, true);
1470 EXPECT_STR_EQ("abc", textfield_
->text());
1473 SendKeyEvent(ui::VKEY_BACK
);
1474 EXPECT_STR_EQ("ab", textfield_
->text());
1475 SendHomeEvent(false);
1476 SendKeyEvent(ui::VKEY_DELETE
);
1477 EXPECT_STR_EQ("b", textfield_
->text());
1478 SendKeyEvent(ui::VKEY_A
, false, true);
1479 SendKeyEvent(ui::VKEY_DELETE
);
1480 EXPECT_STR_EQ("", textfield_
->text());
1481 SendKeyEvent(ui::VKEY_Z
, false, true);
1482 EXPECT_STR_EQ("b", textfield_
->text());
1483 SendKeyEvent(ui::VKEY_Z
, false, true);
1484 EXPECT_STR_EQ("ab", textfield_
->text());
1485 SendKeyEvent(ui::VKEY_Z
, false, true);
1486 EXPECT_STR_EQ("abc", textfield_
->text());
1487 SendKeyEvent(ui::VKEY_Z
, true, true);
1488 EXPECT_STR_EQ("ab", textfield_
->text());
1489 SendKeyEvent(ui::VKEY_Z
, true, true);
1490 EXPECT_STR_EQ("b", textfield_
->text());
1491 SendKeyEvent(ui::VKEY_Z
, true, true);
1492 EXPECT_STR_EQ("", textfield_
->text());
1493 SendKeyEvent(ui::VKEY_Z
, true, true);
1494 EXPECT_STR_EQ("", textfield_
->text());
1497 // Most platforms support Ctrl+Y as an alternative to Ctrl+Shift+Z, but on Mac
1498 // that is bound to "Show full history", so is not mapped as an editing
1499 // command. So, on Mac, send Cmd+Shift+Z.
1500 #if !defined(OS_MACOSX)
1502 // Test that Ctrl+Y works for Redo, as well as Ctrl+Shift+Z.
1503 TEST_F(TextfieldTest
, RedoWithCtrlY
) {
1505 SendKeyEvent(ui::VKEY_A
);
1506 EXPECT_STR_EQ("a", textfield_
->text());
1507 SendKeyEvent(ui::VKEY_Z
, false, true);
1508 EXPECT_STR_EQ("", textfield_
->text());
1509 SendKeyEvent(ui::VKEY_Y
, false, true);
1510 EXPECT_STR_EQ("a", textfield_
->text());
1511 SendKeyEvent(ui::VKEY_Z
, false, true);
1512 EXPECT_STR_EQ("", textfield_
->text());
1513 SendKeyEvent(ui::VKEY_Z
, true, true);
1514 EXPECT_STR_EQ("a", textfield_
->text());
1517 #endif // !defined(OS_MACOSX)
1519 TEST_F(TextfieldTest
, CutCopyPaste
) {
1522 // Ensure IDS_APP_CUT cuts.
1523 textfield_
->SetText(ASCIIToUTF16("123"));
1524 textfield_
->SelectAll(false);
1525 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
1526 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
1527 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1528 EXPECT_STR_EQ("", textfield_
->text());
1529 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1531 // Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
1532 textfield_
->SetText(ASCIIToUTF16("456"));
1533 textfield_
->SelectAll(false);
1534 SendKeyEvent(ui::VKEY_X
, true, false, true, false);
1535 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1536 EXPECT_STR_EQ("456", textfield_
->text());
1537 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1538 SendKeyEvent(ui::VKEY_X
, false, true);
1539 EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1540 EXPECT_STR_EQ("", textfield_
->text());
1541 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1543 // Ensure [Shift]+[Delete] cuts.
1544 textfield_
->SetText(ASCIIToUTF16("123"));
1545 textfield_
->SelectAll(false);
1547 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1548 EXPECT_STR_EQ("", textfield_
->text());
1549 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1551 // Ensure IDS_APP_COPY copies.
1552 textfield_
->SetText(ASCIIToUTF16("789"));
1553 textfield_
->SelectAll(false);
1554 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
1555 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
1556 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1557 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1559 // Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
1560 textfield_
->SetText(ASCIIToUTF16("012"));
1561 textfield_
->SelectAll(false);
1562 SendKeyEvent(ui::VKEY_C
, true, false, true, false);
1563 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1564 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1565 SendKeyEvent(ui::VKEY_C
, false, true);
1566 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1567 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1569 // Ensure [Ctrl]+[Insert] copies.
1570 textfield_
->SetText(ASCIIToUTF16("345"));
1571 textfield_
->SelectAll(false);
1572 SendAlternateCopy();
1573 EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1574 EXPECT_STR_EQ("345", textfield_
->text());
1575 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1577 // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
1578 // also ensure that [Ctrl]+[Alt]+[V] does nothing.
1579 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "abc");
1580 textfield_
->SetText(base::string16());
1581 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
1582 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
1583 EXPECT_STR_EQ("abc", textfield_
->text());
1584 SendKeyEvent(ui::VKEY_V
, false, true);
1585 EXPECT_STR_EQ("abcabc", textfield_
->text());
1586 SendAlternatePaste();
1587 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1588 SendKeyEvent(ui::VKEY_V
, true, false, true, false);
1589 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1591 // Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
1592 textfield_
->SelectAll(false);
1593 SendKeyEvent(ui::VKEY_INSERT
, true, true);
1594 EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1595 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1596 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1599 TEST_F(TextfieldTest
, OvertypeMode
) {
1601 // Overtype mode should be disabled (no-op [Insert]).
1602 textfield_
->SetText(ASCIIToUTF16("2"));
1603 const bool shift
= false;
1604 SendHomeEvent(shift
);
1605 // Note: On Mac, there is no insert key. Insert sends kVK_Help. Currently,
1606 // since there is no overtype on toolkit-views, the behavior happens to match.
1607 // However, there's no enable-overtype equivalent key combination on OSX.
1608 SendKeyEvent(ui::VKEY_INSERT
);
1609 SendKeyEvent(ui::VKEY_1
, false, false);
1610 EXPECT_STR_EQ("12", textfield_
->text());
1613 TEST_F(TextfieldTest
, TextCursorDisplayTest
) {
1615 // LTR-RTL string in LTR context.
1617 EXPECT_STR_EQ("a", textfield_
->text());
1618 int x
= GetCursorBounds().x();
1622 EXPECT_STR_EQ("ab", textfield_
->text());
1623 x
= GetCursorBounds().x();
1624 EXPECT_LT(prev_x
, x
);
1627 SendKeyEvent(0x05E1);
1628 EXPECT_EQ(WideToUTF16(L
"ab\x05E1"), textfield_
->text());
1629 x
= GetCursorBounds().x();
1630 EXPECT_GE(1, std::abs(x
- prev_x
));
1632 SendKeyEvent(0x05E2);
1633 EXPECT_EQ(WideToUTF16(L
"ab\x05E1\x5E2"), textfield_
->text());
1634 x
= GetCursorBounds().x();
1635 EXPECT_GE(1, std::abs(x
- prev_x
));
1638 SendKeyEvent(ui::VKEY_A
, false, true);
1639 SendKeyEvent(ui::VKEY_DELETE
);
1641 // RTL-LTR string in LTR context.
1642 SendKeyEvent(0x05E1);
1643 EXPECT_EQ(WideToUTF16(L
"\x05E1"), textfield_
->text());
1644 x
= GetCursorBounds().x();
1645 EXPECT_EQ(GetDisplayRect().x(), x
);
1648 SendKeyEvent(0x05E2);
1649 EXPECT_EQ(WideToUTF16(L
"\x05E1\x05E2"), textfield_
->text());
1650 x
= GetCursorBounds().x();
1651 EXPECT_GE(1, std::abs(x
- prev_x
));
1654 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"a"), textfield_
->text());
1655 x
= GetCursorBounds().x();
1656 EXPECT_LT(prev_x
, x
);
1660 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"ab"), textfield_
->text());
1661 x
= GetCursorBounds().x();
1662 EXPECT_LT(prev_x
, x
);
1665 TEST_F(TextfieldTest
, TextCursorDisplayInRTLTest
) {
1666 std::string locale
= l10n_util::GetApplicationLocale("");
1667 base::i18n::SetICUDefaultLocale("he");
1670 // LTR-RTL string in RTL context.
1672 EXPECT_STR_EQ("a", textfield_
->text());
1673 int x
= GetCursorBounds().x();
1674 EXPECT_EQ(GetDisplayRect().right() - 1, x
);
1678 EXPECT_STR_EQ("ab", textfield_
->text());
1679 x
= GetCursorBounds().x();
1680 EXPECT_GE(1, std::abs(x
- prev_x
));
1682 SendKeyEvent(0x05E1);
1683 EXPECT_EQ(WideToUTF16(L
"ab\x05E1"), textfield_
->text());
1684 x
= GetCursorBounds().x();
1685 EXPECT_GT(prev_x
, x
);
1688 SendKeyEvent(0x05E2);
1689 EXPECT_EQ(WideToUTF16(L
"ab\x05E1\x5E2"), textfield_
->text());
1690 x
= GetCursorBounds().x();
1691 EXPECT_GT(prev_x
, x
);
1694 SendKeyEvent(ui::VKEY_A
, false, true);
1695 SendKeyEvent(ui::VKEY_DELETE
);
1697 // RTL-LTR string in RTL context.
1698 SendKeyEvent(0x05E1);
1699 EXPECT_EQ(WideToUTF16(L
"\x05E1"), textfield_
->text());
1700 x
= GetCursorBounds().x();
1703 SendKeyEvent(0x05E2);
1704 EXPECT_EQ(WideToUTF16(L
"\x05E1\x05E2"), textfield_
->text());
1705 x
= GetCursorBounds().x();
1706 EXPECT_GT(prev_x
, x
);
1710 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"a"), textfield_
->text());
1711 x
= GetCursorBounds().x();
1712 EXPECT_GE(1, std::abs(x
- prev_x
));
1716 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"ab"), textfield_
->text());
1717 x
= GetCursorBounds().x();
1718 EXPECT_GE(1, std::abs(x
- prev_x
));
1721 base::i18n::SetICUDefaultLocale(locale
);
1724 TEST_F(TextfieldTest
, HitInsideTextAreaTest
) {
1726 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
1727 std::vector
<gfx::Rect
> cursor_bounds
;
1729 // Save each cursor bound.
1730 gfx::SelectionModel
sel(0, gfx::CURSOR_FORWARD
);
1731 cursor_bounds
.push_back(GetCursorBounds(sel
));
1733 sel
= gfx::SelectionModel(1, gfx::CURSOR_BACKWARD
);
1734 gfx::Rect bound
= GetCursorBounds(sel
);
1735 sel
= gfx::SelectionModel(1, gfx::CURSOR_FORWARD
);
1736 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1737 cursor_bounds
.push_back(bound
);
1739 // Check that a cursor at the end of the Latin portion of the text is at the
1740 // same position as a cursor placed at the end of the RTL Hebrew portion.
1741 sel
= gfx::SelectionModel(2, gfx::CURSOR_BACKWARD
);
1742 bound
= GetCursorBounds(sel
);
1743 sel
= gfx::SelectionModel(4, gfx::CURSOR_BACKWARD
);
1744 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1745 cursor_bounds
.push_back(bound
);
1747 sel
= gfx::SelectionModel(3, gfx::CURSOR_BACKWARD
);
1748 bound
= GetCursorBounds(sel
);
1749 sel
= gfx::SelectionModel(3, gfx::CURSOR_FORWARD
);
1750 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1751 cursor_bounds
.push_back(bound
);
1753 sel
= gfx::SelectionModel(2, gfx::CURSOR_FORWARD
);
1754 bound
= GetCursorBounds(sel
);
1755 sel
= gfx::SelectionModel(4, gfx::CURSOR_FORWARD
);
1756 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1757 cursor_bounds
.push_back(bound
);
1759 // Expected cursor position when clicking left and right of each character.
1760 size_t cursor_pos_expected
[] = {0, 1, 1, 2, 4, 3, 3, 2};
1763 for (int i
= 0; i
< static_cast<int>(cursor_bounds
.size() - 1); ++i
) {
1764 int half_width
= (cursor_bounds
[i
+ 1].x() - cursor_bounds
[i
].x()) / 2;
1765 MouseClick(cursor_bounds
[i
], half_width
/ 2);
1766 EXPECT_EQ(cursor_pos_expected
[index
++], textfield_
->GetCursorPosition());
1768 // To avoid trigger double click. Not using sleep() since it takes longer
1769 // for the test to run if using sleep().
1770 NonClientMouseClick();
1772 MouseClick(cursor_bounds
[i
+ 1], - (half_width
/ 2));
1773 EXPECT_EQ(cursor_pos_expected
[index
++], textfield_
->GetCursorPosition());
1775 NonClientMouseClick();
1779 TEST_F(TextfieldTest
, HitOutsideTextAreaTest
) {
1782 // LTR-RTL string in LTR context.
1783 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
1785 const bool shift
= false;
1786 SendHomeEvent(shift
);
1787 gfx::Rect bound
= GetCursorBounds();
1788 MouseClick(bound
, -10);
1789 EXPECT_EQ(bound
, GetCursorBounds());
1791 SendEndEvent(shift
);
1792 bound
= GetCursorBounds();
1793 MouseClick(bound
, 10);
1794 EXPECT_EQ(bound
, GetCursorBounds());
1796 NonClientMouseClick();
1798 // RTL-LTR string in LTR context.
1799 textfield_
->SetText(WideToUTF16(L
"\x05E1\x5E2" L
"ab"));
1801 SendHomeEvent(shift
);
1802 bound
= GetCursorBounds();
1803 MouseClick(bound
, 10);
1804 EXPECT_EQ(bound
, GetCursorBounds());
1806 SendEndEvent(shift
);
1807 bound
= GetCursorBounds();
1808 MouseClick(bound
, -10);
1809 EXPECT_EQ(bound
, GetCursorBounds());
1812 TEST_F(TextfieldTest
, HitOutsideTextAreaInRTLTest
) {
1813 std::string locale
= l10n_util::GetApplicationLocale("");
1814 base::i18n::SetICUDefaultLocale("he");
1818 // RTL-LTR string in RTL context.
1819 textfield_
->SetText(WideToUTF16(L
"\x05E1\x5E2" L
"ab"));
1820 const bool shift
= false;
1821 SendHomeEvent(shift
);
1822 gfx::Rect bound
= GetCursorBounds();
1823 MouseClick(bound
, 10);
1824 EXPECT_EQ(bound
, GetCursorBounds());
1826 SendEndEvent(shift
);
1827 bound
= GetCursorBounds();
1828 MouseClick(bound
, -10);
1829 EXPECT_EQ(bound
, GetCursorBounds());
1831 NonClientMouseClick();
1833 // LTR-RTL string in RTL context.
1834 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
1835 SendHomeEvent(shift
);
1836 bound
= GetCursorBounds();
1837 MouseClick(bound
, -10);
1838 EXPECT_EQ(bound
, GetCursorBounds());
1840 SendEndEvent(shift
);
1841 bound
= GetCursorBounds();
1842 MouseClick(bound
, 10);
1843 EXPECT_EQ(bound
, GetCursorBounds());
1846 base::i18n::SetICUDefaultLocale(locale
);
1849 TEST_F(TextfieldTest
, OverflowTest
) {
1853 for (int i
= 0; i
< 500; ++i
)
1855 SendKeyEvent(kHebrewLetterSamekh
);
1856 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1858 // Test mouse pointing.
1859 MouseClick(GetCursorBounds(), -1);
1860 EXPECT_EQ(500U, textfield_
->GetCursorPosition());
1863 SendKeyEvent(ui::VKEY_A
, false, true);
1864 SendKeyEvent(ui::VKEY_DELETE
);
1866 for (int i
= 0; i
< 500; ++i
)
1867 SendKeyEvent(kHebrewLetterSamekh
);
1869 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1871 MouseClick(GetCursorBounds(), -1);
1872 EXPECT_EQ(501U, textfield_
->GetCursorPosition());
1875 TEST_F(TextfieldTest
, OverflowInRTLTest
) {
1876 std::string locale
= l10n_util::GetApplicationLocale("");
1877 base::i18n::SetICUDefaultLocale("he");
1882 for (int i
= 0; i
< 500; ++i
)
1884 SendKeyEvent(kHebrewLetterSamekh
);
1885 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1887 MouseClick(GetCursorBounds(), 1);
1888 EXPECT_EQ(501U, textfield_
->GetCursorPosition());
1891 SendKeyEvent(ui::VKEY_A
, false, true);
1892 SendKeyEvent(ui::VKEY_DELETE
);
1894 for (int i
= 0; i
< 500; ++i
)
1895 SendKeyEvent(kHebrewLetterSamekh
);
1897 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1899 MouseClick(GetCursorBounds(), 1);
1900 EXPECT_EQ(500U, textfield_
->GetCursorPosition());
1903 base::i18n::SetICUDefaultLocale(locale
);
1906 TEST_F(TextfieldTest
, GetCompositionCharacterBoundsTest
) {
1908 ui::CompositionText composition
;
1909 composition
.text
= UTF8ToUTF16("abc123");
1910 const uint32 char_count
= static_cast<uint32
>(composition
.text
.length());
1911 ui::TextInputClient
* client
= textfield_
->GetTextInputClient();
1913 // Compare the composition character bounds with surrounding cursor bounds.
1914 for (uint32 i
= 0; i
< char_count
; ++i
) {
1915 composition
.selection
= gfx::Range(i
);
1916 client
->SetCompositionText(composition
);
1917 gfx::Point cursor_origin
= GetCursorBounds().origin();
1918 views::View::ConvertPointToScreen(textfield_
, &cursor_origin
);
1920 composition
.selection
= gfx::Range(i
+ 1);
1921 client
->SetCompositionText(composition
);
1922 gfx::Point next_cursor_bottom_left
= GetCursorBounds().bottom_left();
1923 views::View::ConvertPointToScreen(textfield_
, &next_cursor_bottom_left
);
1925 gfx::Rect character
;
1926 EXPECT_TRUE(client
->GetCompositionCharacterBounds(i
, &character
));
1927 EXPECT_EQ(character
.origin(), cursor_origin
) << " i=" << i
;
1928 EXPECT_EQ(character
.bottom_right(), next_cursor_bottom_left
) << " i=" << i
;
1931 // Return false if the index is out of range.
1933 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
, &rect
));
1934 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
+ 1, &rect
));
1935 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
+ 100, &rect
));
1938 TEST_F(TextfieldTest
, GetCompositionCharacterBounds_ComplexText
) {
1941 const base::char16 kUtf16Chars
[] = {
1944 // U+1F408 (CAT) as surrogate pair
1946 // U+5642 as Ideographic Variation Sequences
1947 0x5642, 0xDB40, 0xDD00,
1948 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences
1953 const size_t kUtf16CharsCount
= arraysize(kUtf16Chars
);
1955 ui::CompositionText composition
;
1956 composition
.text
.assign(kUtf16Chars
, kUtf16Chars
+ kUtf16CharsCount
);
1957 ui::TextInputClient
* client
= textfield_
->GetTextInputClient();
1958 client
->SetCompositionText(composition
);
1960 // Make sure GetCompositionCharacterBounds never fails for index.
1961 gfx::Rect rects
[kUtf16CharsCount
];
1962 gfx::Rect prev_cursor
= GetCursorBounds();
1963 for (uint32 i
= 0; i
< kUtf16CharsCount
; ++i
)
1964 EXPECT_TRUE(client
->GetCompositionCharacterBounds(i
, &rects
[i
]));
1966 // Here we might expect the following results but it actually depends on how
1967 // Uniscribe or HarfBuzz treats them with given font.
1968 // - rects[1] == rects[2]
1969 // - rects[3] == rects[4] == rects[5]
1970 // - rects[6] == rects[7]
1973 // The word we select by double clicking should remain selected regardless of
1974 // where we drag the mouse afterwards without releasing the left button.
1975 TEST_F(TextfieldTest
, KeepInitiallySelectedWord
) {
1978 textfield_
->SetText(ASCIIToUTF16("abc def ghi"));
1980 textfield_
->SelectRange(gfx::Range(5, 5));
1981 const gfx::Rect middle_cursor
= GetCursorBounds();
1982 textfield_
->SelectRange(gfx::Range(0, 0));
1983 const gfx::Point beginning
= GetCursorBounds().origin();
1985 // Double click, but do not release the left button.
1986 MouseClick(middle_cursor
, 0);
1987 const gfx::Point
middle(middle_cursor
.x(),
1988 middle_cursor
.y() + middle_cursor
.height() / 2);
1989 ui::MouseEvent
press_event(ui::ET_MOUSE_PRESSED
, middle
, middle
,
1990 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1991 ui::EF_LEFT_MOUSE_BUTTON
);
1992 textfield_
->OnMousePressed(press_event
);
1993 EXPECT_EQ(gfx::Range(4, 7), textfield_
->GetSelectedRange());
1995 // Drag the mouse to the beginning of the textfield.
1996 ui::MouseEvent
drag_event(ui::ET_MOUSE_DRAGGED
, beginning
, beginning
,
1997 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1998 textfield_
->OnMouseDragged(drag_event
);
1999 EXPECT_EQ(gfx::Range(7, 0), textfield_
->GetSelectedRange());
2002 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2003 // flaky: http://crbug.com/396477
2004 TEST_F(TextfieldTest
, DISABLED_SelectionClipboard
) {
2006 textfield_
->SetText(ASCIIToUTF16("0123"));
2007 gfx::Point
point_1(GetCursorPositionX(1), 0);
2008 gfx::Point
point_2(GetCursorPositionX(2), 0);
2009 gfx::Point
point_3(GetCursorPositionX(3), 0);
2010 gfx::Point
point_4(GetCursorPositionX(4), 0);
2012 // Text selected by the mouse should be placed on the selection clipboard.
2013 ui::MouseEvent
press(ui::ET_MOUSE_PRESSED
, point_1
, point_1
,
2014 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2015 ui::EF_LEFT_MOUSE_BUTTON
);
2016 textfield_
->OnMousePressed(press
);
2017 ui::MouseEvent
drag(ui::ET_MOUSE_DRAGGED
, point_3
, point_3
,
2018 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2019 ui::EF_LEFT_MOUSE_BUTTON
);
2020 textfield_
->OnMouseDragged(drag
);
2021 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, point_3
, point_3
,
2022 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2023 ui::EF_LEFT_MOUSE_BUTTON
);
2024 textfield_
->OnMouseReleased(release
);
2025 EXPECT_EQ(gfx::Range(1, 3), textfield_
->GetSelectedRange());
2026 EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2028 // Select-all should update the selection clipboard.
2029 SendKeyEvent(ui::VKEY_A
, false, true);
2030 EXPECT_EQ(gfx::Range(0, 4), textfield_
->GetSelectedRange());
2031 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2032 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2034 // Shift-click selection modifications should update the clipboard.
2035 NonClientMouseClick();
2036 ui::MouseEvent
press_2(ui::ET_MOUSE_PRESSED
, point_2
, point_2
,
2037 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2038 ui::EF_LEFT_MOUSE_BUTTON
);
2039 press_2
.set_flags(press_2
.flags() | ui::EF_SHIFT_DOWN
);
2040 #if defined(USE_X11)
2041 ui::UpdateX11EventForFlags(&press_2
);
2043 textfield_
->OnMousePressed(press_2
);
2044 ui::MouseEvent
release_2(ui::ET_MOUSE_RELEASED
, point_2
, point_2
,
2045 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2046 ui::EF_LEFT_MOUSE_BUTTON
);
2047 textfield_
->OnMouseReleased(release_2
);
2048 EXPECT_EQ(gfx::Range(0, 2), textfield_
->GetSelectedRange());
2049 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2050 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2052 // Shift-Left/Right should update the selection clipboard.
2053 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
2054 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2055 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2056 SendKeyEvent(ui::VKEY_LEFT
, true, false);
2057 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2058 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2059 SendKeyEvent(ui::VKEY_RIGHT
, true, true);
2060 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2061 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2063 // Moving the cursor without a selection should not change the clipboard.
2064 SendKeyEvent(ui::VKEY_LEFT
, false, false);
2065 EXPECT_EQ(gfx::Range(0, 0), textfield_
->GetSelectedRange());
2066 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2067 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2069 // Middle clicking should paste at the mouse (not cursor) location.
2070 // The cursor should be placed at the end of the pasted text.
2071 ui::MouseEvent
middle(ui::ET_MOUSE_PRESSED
, point_4
, point_4
,
2072 ui::EventTimeForNow(), ui::EF_MIDDLE_MOUSE_BUTTON
,
2073 ui::EF_MIDDLE_MOUSE_BUTTON
);
2074 textfield_
->OnMousePressed(middle
);
2075 EXPECT_STR_EQ("01230123", textfield_
->text());
2076 EXPECT_EQ(gfx::Range(8, 8), textfield_
->GetSelectedRange());
2077 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2079 // Middle clicking on an unfocused textfield should focus it and paste.
2080 textfield_
->GetFocusManager()->ClearFocus();
2081 EXPECT_FALSE(textfield_
->HasFocus());
2082 textfield_
->OnMousePressed(middle
);
2083 EXPECT_TRUE(textfield_
->HasFocus());
2084 EXPECT_STR_EQ("012301230123", textfield_
->text());
2085 EXPECT_EQ(gfx::Range(8, 8), textfield_
->GetSelectedRange());
2086 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2088 // Middle clicking with an empty selection clipboard should still focus.
2089 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, std::string());
2090 textfield_
->GetFocusManager()->ClearFocus();
2091 EXPECT_FALSE(textfield_
->HasFocus());
2092 textfield_
->OnMousePressed(middle
);
2093 EXPECT_TRUE(textfield_
->HasFocus());
2094 EXPECT_STR_EQ("012301230123", textfield_
->text());
2095 EXPECT_EQ(gfx::Range(4, 4), textfield_
->GetSelectedRange());
2096 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
).empty());
2098 // Middle clicking in the selection should clear the clipboard and selection.
2099 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "foo");
2100 textfield_
->SelectRange(gfx::Range(2, 6));
2101 textfield_
->OnMousePressed(middle
);
2102 EXPECT_STR_EQ("012301230123", textfield_
->text());
2103 EXPECT_EQ(gfx::Range(6, 6), textfield_
->GetSelectedRange());
2104 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
).empty());
2106 // Double and triple clicking should update the clipboard contents.
2107 textfield_
->SetText(ASCIIToUTF16("ab cd ef"));
2108 gfx::Point
word(GetCursorPositionX(4), 0);
2109 ui::MouseEvent
press_word(ui::ET_MOUSE_PRESSED
, word
, word
,
2110 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2111 ui::EF_LEFT_MOUSE_BUTTON
);
2112 textfield_
->OnMousePressed(press_word
);
2113 ui::MouseEvent
release_word(ui::ET_MOUSE_RELEASED
, word
, word
,
2114 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2115 ui::EF_LEFT_MOUSE_BUTTON
);
2116 textfield_
->OnMouseReleased(release_word
);
2117 ui::MouseEvent
double_click(ui::ET_MOUSE_PRESSED
, word
, word
,
2118 ui::EventTimeForNow(),
2119 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_DOUBLE_CLICK
,
2120 ui::EF_LEFT_MOUSE_BUTTON
);
2121 textfield_
->OnMousePressed(double_click
);
2122 textfield_
->OnMouseReleased(release_word
);
2123 EXPECT_EQ(gfx::Range(3, 5), textfield_
->GetSelectedRange());
2124 EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2125 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2126 textfield_
->OnMousePressed(press_word
);
2127 textfield_
->OnMouseReleased(release_word
);
2128 EXPECT_EQ(gfx::Range(0, 8), textfield_
->GetSelectedRange());
2129 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2130 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2132 // Selecting a range of text without any user interaction should not change
2133 // the clipboard content.
2134 textfield_
->SelectRange(gfx::Range(0, 3));
2135 EXPECT_STR_EQ("ab ", textfield_
->GetSelectedText());
2136 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2137 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2139 SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
, "other");
2140 textfield_
->SelectAll(false);
2141 EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2142 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2146 // Long_Press gesture in Textfield can initiate a drag and drop now.
2147 TEST_F(TextfieldTest
, TestLongPressInitiatesDragDrop
) {
2149 textfield_
->SetText(ASCIIToUTF16("Hello string world"));
2151 // Ensure the textfield will provide selected text for drag data.
2152 textfield_
->SelectRange(gfx::Range(6, 12));
2153 const gfx::Point
kStringPoint(GetCursorPositionX(9), 0);
2155 // Enable touch-drag-drop to make long press effective.
2156 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2157 switches::kEnableTouchDragDrop
);
2159 // Create a long press event in the selected region should start a drag.
2160 GestureEventForTest
long_press(
2163 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2164 textfield_
->OnGestureEvent(&long_press
);
2165 EXPECT_TRUE(textfield_
->CanStartDragForView(NULL
, kStringPoint
,
2169 TEST_F(TextfieldTest
, GetTextfieldBaseline_FontFallbackTest
) {
2171 textfield_
->SetText(UTF8ToUTF16("abc"));
2172 const int old_baseline
= textfield_
->GetBaseline();
2174 // Set text which may fall back to a font which has taller baseline than
2175 // the default font.
2176 textfield_
->SetText(UTF8ToUTF16("\xE0\xB9\x91"));
2177 const int new_baseline
= textfield_
->GetBaseline();
2179 // Regardless of the text, the baseline must be the same.
2180 EXPECT_EQ(new_baseline
, old_baseline
);
2183 // Tests that a textfield view can be destroyed from OnKeyEvent() on its
2184 // controller and it does not crash.
2185 TEST_F(TextfieldTest
, DestroyingTextfieldFromOnKeyEvent
) {
2188 // The controller assumes ownership of the textfield.
2189 TextfieldDestroyerController
controller(textfield_
);
2190 EXPECT_TRUE(controller
.target());
2192 // Send a key to trigger OnKeyEvent().
2193 SendKeyEvent(ui::VKEY_RETURN
);
2195 EXPECT_FALSE(controller
.target());
2198 class TextfieldTouchSelectionTest
: public TextfieldTest
{
2201 void SetUp() override
{
2202 TextfieldTest::SetUp();
2203 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2204 switches::kEnableTouchEditing
);
2208 // Simulates a complete tap.
2209 void Tap(const gfx::Point
& point
) {
2210 GestureEventForTest
begin(
2211 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_BEGIN
));
2212 textfield_
->OnGestureEvent(&begin
);
2214 GestureEventForTest
tap_down(
2215 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN
));
2216 textfield_
->OnGestureEvent(&tap_down
);
2218 GestureEventForTest
show_press(
2221 ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS
));
2222 textfield_
->OnGestureEvent(&show_press
);
2224 ui::GestureEventDetails
tap_details(ui::ET_GESTURE_TAP
);
2225 tap_details
.set_tap_count(1);
2226 GestureEventForTest
tap(point
.x(), point
.y(), tap_details
);
2227 textfield_
->OnGestureEvent(&tap
);
2229 GestureEventForTest
end(
2230 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_END
));
2231 textfield_
->OnGestureEvent(&end
);
2236 // Touch selection and dragging currently only works for chromeos.
2237 #if defined(OS_CHROMEOS)
2238 TEST_F(TextfieldTouchSelectionTest
, TouchSelectionAndDraggingTest
) {
2240 textfield_
->SetText(ASCIIToUTF16("hello world"));
2241 EXPECT_FALSE(test_api_
->touch_selection_controller());
2242 const int x
= GetCursorPositionX(2);
2244 // Tapping on the textfield should turn on the TouchSelectionController.
2245 ui::GestureEventDetails
tap_details(ui::ET_GESTURE_TAP
);
2246 tap_details
.set_tap_count(1);
2247 GestureEventForTest
tap(x
, 0, tap_details
);
2248 textfield_
->OnGestureEvent(&tap
);
2249 EXPECT_TRUE(test_api_
->touch_selection_controller());
2251 // Un-focusing the textfield should reset the TouchSelectionController
2252 textfield_
->GetFocusManager()->ClearFocus();
2253 EXPECT_FALSE(test_api_
->touch_selection_controller());
2254 textfield_
->RequestFocus();
2256 // With touch editing enabled, long press should not show context menu.
2257 // Instead, select word and invoke TouchSelectionController.
2258 GestureEventForTest
long_press_1(
2259 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2260 textfield_
->OnGestureEvent(&long_press_1
);
2261 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2262 EXPECT_TRUE(test_api_
->touch_selection_controller());
2263 EXPECT_TRUE(long_press_1
.handled());
2265 // With touch drag drop enabled, long pressing in the selected region should
2266 // start a drag and remove TouchSelectionController.
2267 ASSERT_TRUE(switches::IsTouchDragDropEnabled());
2268 GestureEventForTest
long_press_2(
2269 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2270 textfield_
->OnGestureEvent(&long_press_2
);
2271 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2272 EXPECT_FALSE(test_api_
->touch_selection_controller());
2273 EXPECT_FALSE(long_press_2
.handled());
2275 // After disabling touch drag drop, long pressing again in the selection
2276 // region should not do anything.
2277 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2278 switches::kDisableTouchDragDrop
);
2279 ASSERT_FALSE(switches::IsTouchDragDropEnabled());
2280 GestureEventForTest
long_press_3(
2281 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2282 textfield_
->OnGestureEvent(&long_press_3
);
2283 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2284 EXPECT_FALSE(test_api_
->touch_selection_controller());
2285 EXPECT_FALSE(long_press_3
.handled());
2289 TEST_F(TextfieldTouchSelectionTest
, TouchSelectionInUnfocusableTextfield
) {
2291 textfield_
->SetText(ASCIIToUTF16("hello world"));
2292 gfx::Point
touch_point(GetCursorPositionX(2), 0);
2294 // Disable textfield and tap on it. Touch text selection should not get
2296 textfield_
->SetEnabled(false);
2298 EXPECT_FALSE(test_api_
->touch_selection_controller());
2299 textfield_
->SetEnabled(true);
2301 // Make textfield unfocusable and tap on it. Touch text selection should not
2303 textfield_
->SetFocusable(false);
2305 EXPECT_FALSE(textfield_
->HasFocus());
2306 EXPECT_FALSE(test_api_
->touch_selection_controller());
2307 textfield_
->SetFocusable(true);
2310 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
2311 #if defined(OS_MACOSX) && !defined(USE_AURA)
2312 #define MAYBE_TapOnSelection DISABLED_TapOnSelection
2314 #define MAYBE_TapOnSelection TapOnSelection
2317 TEST_F(TextfieldTouchSelectionTest
, MAYBE_TapOnSelection
) {
2319 textfield_
->SetText(ASCIIToUTF16("hello world"));
2320 gfx::Range
sel_range(2, 7);
2321 gfx::Range
tap_range(5, 5);
2322 gfx::Rect tap_rect
=
2323 GetCursorBounds(gfx::SelectionModel(tap_range
, gfx::CURSOR_FORWARD
));
2324 gfx::Point tap_point
= tap_rect
.CenterPoint();
2326 // Select range |sel_range| and check if touch selection handles are not
2327 // present and correct range is selected.
2328 textfield_
->SetSelectionRange(sel_range
);
2330 textfield_
->GetSelectionRange(&range
);
2331 EXPECT_FALSE(test_api_
->touch_selection_controller());
2332 EXPECT_EQ(sel_range
, range
);
2334 // Tap on selection and check if touch selectoin handles are shown, but
2335 // selection range is not modified.
2337 textfield_
->GetSelectionRange(&range
);
2338 EXPECT_TRUE(test_api_
->touch_selection_controller());
2339 EXPECT_EQ(sel_range
, range
);
2341 // Tap again on selection and check if touch selection handles are still
2342 // present and selection is changed to a cursor at tap location.
2344 textfield_
->GetSelectionRange(&range
);
2345 EXPECT_TRUE(test_api_
->touch_selection_controller());
2346 EXPECT_EQ(tap_range
, range
);
2349 TEST_F(TextfieldTest
, AccessiblePasswordTest
) {
2351 textfield_
->SetText(ASCIIToUTF16("password"));
2353 ui::AXViewState state_regular
;
2354 textfield_
->GetAccessibleState(&state_regular
);
2355 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD
, state_regular
.role
);
2356 EXPECT_EQ(ASCIIToUTF16("password"), state_regular
.value
);
2357 EXPECT_FALSE(state_regular
.HasStateFlag(ui::AX_STATE_PROTECTED
));
2359 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
2360 ui::AXViewState state_protected
;
2361 textfield_
->GetAccessibleState(&state_protected
);
2362 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD
, state_protected
.role
);
2363 EXPECT_EQ(ASCIIToUTF16("********"), state_protected
.value
);
2364 EXPECT_TRUE(state_protected
.HasStateFlag(ui::AX_STATE_PROTECTED
));
2367 } // namespace views