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