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