| OLD | NEW |
| (Empty) |
| 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 | |
| 48 using base::ASCIIToUTF16; | |
| 49 using base::UTF8ToUTF16; | |
| 50 using base::WideToUTF16; | |
| 51 | |
| 52 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) | |
| 53 | |
| 54 namespace { | |
| 55 | |
| 56 const base::char16 kHebrewLetterSamekh = 0x05E1; | |
| 57 | |
| 58 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults. | |
| 59 class 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. | |
| 104 class 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. | |
| 115 class 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 | |
| 135 base::string16 GetClipboardText(ui::ClipboardType type) { | |
| 136 base::string16 text; | |
| 137 ui::Clipboard::GetForCurrentThread()->ReadText(type, &text); | |
| 138 return text; | |
| 139 } | |
| 140 | |
| 141 void SetClipboardText(ui::ClipboardType type, const std::string& text) { | |
| 142 ui::ScopedClipboardWriter(type).WriteText(ASCIIToUTF16(text)); | |
| 143 } | |
| 144 | |
| 145 } // namespace | |
| 146 | |
| 147 namespace views { | |
| 148 | |
| 149 class 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 | |
| 386 TEST_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 | |
| 409 TEST_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 | |
| 423 TEST_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 | |
| 458 TEST_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 | |
| 510 TEST_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 | |
| 548 TEST_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 | |
| 575 TEST_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. | |
| 623 TEST_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 | |
| 669 TEST_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 | |
| 719 TEST_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 | |
| 755 TEST_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 | |
| 778 TEST_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 | |
| 809 TEST_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) | |
| 847 TEST_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 | |
| 899 TEST_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 | |
| 946 TEST_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 | |
| 999 TEST_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 | |
| 1052 TEST_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 | |
| 1082 TEST_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 | |
| 1148 TEST_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 | |
| 1247 TEST_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 | |
| 1341 TEST_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 | |
| 1421 TEST_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 | |
| 1431 TEST_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 | |
| 1483 TEST_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 | |
| 1541 TEST_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 | |
| 1596 TEST_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 | |
| 1628 TEST_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 | |
| 1664 TEST_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 | |
| 1690 TEST_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 | |
| 1721 TEST_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 | |
| 1753 TEST_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. | |
| 1790 TEST_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 | |
| 1819 TEST_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) | |
| 1946 TEST_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 | |
| 1998 TEST_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. | |
| 2022 TEST_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 | |
| 2044 TEST_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. | |
| 2060 TEST_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 | |
| OLD | NEW |