summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormsw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-23 01:40:42 +0000
committermsw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-23 01:40:42 +0000
commita44af4634f25e7e74e13b34c793361849a55b741 (patch)
tree8b05977f9cbb408b543130e775e45d94aaa1e519
parent80f360a3d6b499599615ca70701363f7ddf397a4 (diff)
downloadchromium_src-a44af4634f25e7e74e13b34c793361849a55b741.zip
chromium_src-a44af4634f25e7e74e13b34c793361849a55b741.tar.gz
chromium_src-a44af4634f25e7e74e13b34c793361849a55b741.tar.bz2
Views Textfield: copy-on-select and paste-on-middle-click.
Add Textfield::PasteSelectionClipboard helper function. (used to paste on middle click, update cursor/selection) Add file-local UpdateSelectionClipboard helper function. (used to write non-empty text to the selection clipboard) Call UpdateAfterChange consistently after changes. (not just OnCaretBoundsChanged, SchedulePaint, etc.) Cleanup ExecuteCommand, OnMousePressed/Dragged, etc. Add TextfieldTest.SelectionClipboard unit tests. Make Get/SetClipboardText helpers file-local. BUG=319011 R=erg@chromium.org,oshima@chromium.org TEST=Copy-on-select and paste-on-middle-click work for Linux Aura omnibox and browser textfields (find-in-page, bookmark bubble). NOTRY=true Review URL: https://codereview.chromium.org/73403002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@246478 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/views/controls/textfield/textfield.cc172
-rw-r--r--ui/views/controls/textfield/textfield.h18
-rw-r--r--ui/views/controls/textfield/textfield_unittest.cc200
3 files changed, 254 insertions, 136 deletions
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 88d4c1e..5c6c801 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -9,6 +9,7 @@
#include "base/debug/trace_event.h"
#include "grit/ui_strings.h"
#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drag_utils.h"
#include "ui/base/resource/resource_bundle.h"
@@ -150,8 +151,8 @@ base::i18n::TextDirection Textfield::GetTextDirection() const {
void Textfield::SelectAll(bool reversed) {
model_->SelectAll(reversed);
- OnCaretBoundsChanged();
- SchedulePaint();
+ UpdateSelectionClipboard();
+ UpdateAfterChange(false, true);
}
base::string16 Textfield::GetSelectedText() const {
@@ -160,8 +161,7 @@ base::string16 Textfield::GetSelectedText() const {
void Textfield::ClearSelection() {
model_->ClearSelection();
- OnCaretBoundsChanged();
- SchedulePaint();
+ UpdateAfterChange(false, true);
}
bool Textfield::HasSelection() const {
@@ -244,10 +244,7 @@ const gfx::Range& Textfield::GetSelectedRange() const {
void Textfield::SelectRange(const gfx::Range& range) {
model_->SelectRange(range);
- OnCaretBoundsChanged();
- SchedulePaint();
- NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
+ UpdateAfterChange(false, true);
}
const gfx::SelectionModel& Textfield::GetSelectionModel() const {
@@ -256,8 +253,7 @@ const gfx::SelectionModel& Textfield::GetSelectionModel() const {
void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) {
model_->SelectSelectionModel(sel);
- OnCaretBoundsChanged();
- SchedulePaint();
+ UpdateAfterChange(false, true);
}
size_t Textfield::GetCursorPosition() const {
@@ -373,6 +369,7 @@ bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
case ui::VKEY_A:
if (control && !alt) {
model_->SelectAll(false);
+ UpdateSelectionClipboard();
cursor_changed = true;
}
break;
@@ -400,6 +397,7 @@ bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
control ? gfx::WORD_BREAK : gfx::CHARACTER_BREAK,
(key_code == ui::VKEY_RIGHT) ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT,
shift);
+ UpdateSelectionClipboard();
cursor_changed = render_text->selection() != selection_range;
break;
}
@@ -410,6 +408,7 @@ bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, shift);
else
model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, shift);
+ UpdateSelectionClipboard();
cursor_changed = true;
break;
case ui::VKEY_BACK:
@@ -463,7 +462,6 @@ bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
}
bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
- OnBeforeUserAction();
TrackMouseClicks(event);
if (!controller_ || !controller_->HandleMouseEvent(this, event)) {
@@ -473,36 +471,46 @@ bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
}
if (event.IsOnlyLeftMouseButton()) {
+ OnBeforeUserAction();
initiating_drag_ = false;
- bool can_drag = true;
-
switch (aggregated_clicks_) {
case 0:
- if (can_drag &&
- GetRenderText()->IsPointInSelection(event.location())) {
+ if (GetRenderText()->IsPointInSelection(event.location()))
initiating_drag_ = true;
- } else {
+ else
MoveCursorTo(event.location(), event.IsShiftDown());
- }
break;
case 1:
- MoveCursorTo(event.location(), false);
+ model_->MoveCursorTo(event.location(), false);
model_->SelectWord();
+ UpdateAfterChange(false, true);
double_click_word_ = GetRenderText()->selection();
- OnCaretBoundsChanged();
break;
case 2:
- model_->SelectAll(false);
- OnCaretBoundsChanged();
+ SelectAll(false);
break;
default:
NOTREACHED();
}
+ OnAfterUserAction();
}
- SchedulePaint();
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ if (event.IsOnlyMiddleMouseButton()) {
+ if (GetRenderText()->IsPointInSelection(event.location())) {
+ OnBeforeUserAction();
+ ClearSelection();
+ ui::ScopedClipboardWriter(
+ ui::Clipboard::GetForCurrentThread(),
+ ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16());
+ OnAfterUserAction();
+ } else if(!read_only()) {
+ PasteSelectionClipboard(event);
+ }
+ }
+#endif
}
- OnAfterUserAction();
touch_selection_controller_.reset();
return true;
}
@@ -515,34 +523,33 @@ bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
return true;
}
- if (!event.IsOnlyRightMouseButton()) {
- OnBeforeUserAction();
- MoveCursorTo(event.location(), true);
- if (aggregated_clicks_ == 1) {
- model_->SelectWord();
- // Expand the selection so the initially selected word remains selected.
- gfx::Range selection = GetRenderText()->selection();
- const size_t min = std::min(selection.GetMin(),
- double_click_word_.GetMin());
- const size_t max = std::max(selection.GetMax(),
- double_click_word_.GetMax());
- const bool reversed = selection.is_reversed();
- selection.set_start(reversed ? max : min);
- selection.set_end(reversed ? min : max);
- model_->SelectRange(selection);
- }
- SchedulePaint();
- OnAfterUserAction();
+ OnBeforeUserAction();
+ model_->MoveCursorTo(event.location(), true);
+ if (aggregated_clicks_ == 1) {
+ model_->SelectWord();
+ // Expand the selection so the initially selected word remains selected.
+ gfx::Range selection = GetRenderText()->selection();
+ const size_t min = std::min(selection.GetMin(),
+ double_click_word_.GetMin());
+ const size_t max = std::max(selection.GetMax(),
+ double_click_word_.GetMax());
+ const bool reversed = selection.is_reversed();
+ selection.set_start(reversed ? max : min);
+ selection.set_end(reversed ? min : max);
+ model_->SelectRange(selection);
}
+ UpdateAfterChange(false, true);
+ OnAfterUserAction();
return true;
}
void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
OnBeforeUserAction();
// Cancel suspected drag initiations, the user was clicking in the selection.
- if (initiating_drag_ && MoveCursorTo(event.location(), false))
- SchedulePaint();
+ if (initiating_drag_)
+ MoveCursorTo(event.location(), false);
initiating_drag_ = false;
+ UpdateSelectionClipboard();
OnAfterUserAction();
}
@@ -644,16 +651,14 @@ void Textfield::OnGestureEvent(ui::GestureEvent* event) {
// We don't deselect if the point is in the selection
// because TAP_DOWN may turn into a LONG_PRESS.
- if (!GetRenderText()->IsPointInSelection(event->location()) &&
- MoveCursorTo(event->location(), false))
- SchedulePaint();
+ if (!GetRenderText()->IsPointInSelection(event->location()))
+ MoveCursorTo(event->location(), false);
OnAfterUserAction();
event->SetHandled();
break;
case ui::ET_GESTURE_SCROLL_UPDATE:
OnBeforeUserAction();
- if (MoveCursorTo(event->location(), true))
- SchedulePaint();
+ MoveCursorTo(event->location(), true);
OnAfterUserAction();
event->SetHandled();
break;
@@ -689,8 +694,7 @@ void Textfield::OnGestureEvent(ui::GestureEvent* event) {
model_->SelectWord();
touch_selection_controller_.reset(
ui::TouchSelectionController::create(this));
- OnCaretBoundsChanged();
- SchedulePaint();
+ UpdateAfterChange(false, true);
OnAfterUserAction();
if (touch_selection_controller_)
event->SetHandled();
@@ -899,9 +903,7 @@ void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) {
end_caret.caret_affinity());
OnBeforeUserAction();
- model_->SelectSelectionModel(selection);
- OnCaretBoundsChanged();
- SchedulePaint();
+ SelectSelectionModel(selection);
OnAfterUserAction();
}
@@ -985,46 +987,32 @@ void Textfield::ExecuteCommand(int command_id, int event_flags) {
return;
bool text_changed = false;
+ OnBeforeUserAction();
switch (command_id) {
case IDS_APP_UNDO:
- OnBeforeUserAction();
text_changed = model_->Undo();
- UpdateAfterChange(text_changed, text_changed);
- OnAfterUserAction();
break;
case IDS_APP_CUT:
- OnBeforeUserAction();
text_changed = Cut();
- UpdateAfterChange(text_changed, text_changed);
- OnAfterUserAction();
break;
case IDS_APP_COPY:
- OnBeforeUserAction();
Copy();
- OnAfterUserAction();
break;
case IDS_APP_PASTE:
- OnBeforeUserAction();
text_changed = Paste();
- UpdateAfterChange(text_changed, text_changed);
- OnAfterUserAction();
break;
case IDS_APP_DELETE:
- OnBeforeUserAction();
text_changed = model_->Delete();
- UpdateAfterChange(text_changed, text_changed);
- OnAfterUserAction();
break;
case IDS_APP_SELECT_ALL:
- OnBeforeUserAction();
SelectAll(false);
- UpdateAfterChange(false, true);
- OnAfterUserAction();
break;
default:
NOTREACHED();
break;
}
+ UpdateAfterChange(text_changed, text_changed);
+ OnAfterUserAction();
}
////////////////////////////////////////////////////////////////////////////////
@@ -1200,7 +1188,6 @@ bool Textfield::GetSelectionRange(gfx::Range* range) const {
bool Textfield::SetSelectionRange(const gfx::Range& range) {
if (!ImeEditingAllowed() || !range.IsValid())
return false;
-
OnBeforeUserAction();
SelectRange(range);
OnAfterUserAction();
@@ -1364,11 +1351,9 @@ void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) {
canvas->Restore();
}
-bool Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
- if (!model_->MoveCursorTo(point, select))
- return false;
- OnCaretBoundsChanged();
- return true;
+void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
+ if (model_->MoveCursorTo(point, select))
+ UpdateAfterChange(false, true);
}
void Textfield::OnCaretBoundsChanged() {
@@ -1477,4 +1462,39 @@ void Textfield::CreateTouchSelectionControllerAndNotifyIt() {
touch_selection_controller_->SelectionChanged();
}
+void Textfield::UpdateSelectionClipboard() const {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ if (HasSelection()) {
+ ui::ScopedClipboardWriter(
+ ui::Clipboard::GetForCurrentThread(),
+ ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText());
+ }
+#endif
+}
+
+void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) {
+ DCHECK(event.IsOnlyMiddleMouseButton());
+ DCHECK(!read_only());
+ base::string16 selection_clipboard_text;
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text);
+ if (!selection_clipboard_text.empty()) {
+ OnBeforeUserAction();
+ gfx::Range range = GetSelectionModel().selection();
+ gfx::LogicalCursorDirection affinity = GetSelectionModel().caret_affinity();
+ const gfx::SelectionModel mouse =
+ GetRenderText()->FindCursorPosition(event.location());
+ model_->MoveCursorTo(mouse);
+ model_->InsertText(selection_clipboard_text);
+ // Update the new selection range as needed.
+ if (range.GetMin() >= mouse.caret_pos()) {
+ const size_t length = selection_clipboard_text.length();
+ range = gfx::Range(range.start() + length, range.end() + length);
+ }
+ model_->MoveCursorTo(gfx::SelectionModel(range, affinity));
+ UpdateAfterChange(true, true);
+ OnAfterUserAction();
+ }
+}
+
} // namespace views
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h
index 94d98ae..7596126 100644
--- a/ui/views/controls/textfield/textfield.h
+++ b/ui/views/controls/textfield/textfield.h
@@ -310,9 +310,9 @@ class VIEWS_EXPORT Textfield : public View,
void PaintTextAndCursor(gfx::Canvas* canvas);
// Helper function to call MoveCursorTo on the TextfieldModel.
- bool MoveCursorTo(const gfx::Point& point, bool select);
+ void MoveCursorTo(const gfx::Point& point, bool select);
- // Convenience method to call InputMethod::OnCaretBoundsChanged();
+ // Convenience method to notify the InputMethod and TouchSelectionController.
void OnCaretBoundsChanged();
// Convenience method to call TextfieldController::OnBeforeUserAction();
@@ -346,6 +346,12 @@ class VIEWS_EXPORT Textfield : public View,
void CreateTouchSelectionControllerAndNotifyIt();
+ // Updates the selection clipboard to any non-empty text selection.
+ void UpdateSelectionClipboard() const;
+
+ // Pastes the selection clipboard for the specified mouse event.
+ void PasteSelectionClipboard(const ui::MouseEvent& event);
+
// The text model.
scoped_ptr<TextfieldModel> model_;
@@ -385,8 +391,9 @@ class VIEWS_EXPORT Textfield : public View,
// The input type of this text field.
ui::TextInputType text_input_type_;
- // The duration to reveal the last typed char for password textfields.
+ // The duration and timer to reveal the last typed password character.
base::TimeDelta password_reveal_duration_;
+ base::OneShotTimer<Textfield> password_reveal_timer_;
// True if InputMethod::CancelComposition() should not be called.
bool skip_input_method_cancel_composition_;
@@ -410,11 +417,6 @@ class VIEWS_EXPORT Textfield : public View,
scoped_ptr<ui::TouchSelectionController> touch_selection_controller_;
- // A timer to control the duration of showing the last typed char in
- // password text. When the timer is running, the last typed char is shown
- // and when the time expires, the last typed char is password.
- base::OneShotTimer<Textfield> password_reveal_timer_;
-
// Context menu related members.
scoped_ptr<ui::SimpleMenuModel> context_menu_contents_;
scoped_ptr<views::MenuRunner> context_menu_runner_;
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index 4ab7635..503c656 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -109,6 +109,17 @@ class GestureEventForTest : public ui::GestureEvent {
DISALLOW_COPY_AND_ASSIGN(GestureEventForTest);
};
+base::string16 GetClipboardText(ui::ClipboardType type) {
+ base::string16 text;
+ ui::Clipboard::GetForCurrentThread()->ReadText(type, &text);
+ return text;
+}
+
+void SetClipboardText(ui::ClipboardType type, const std::string& text) {
+ ui::ScopedClipboardWriter(ui::Clipboard::GetForCurrentThread(), type)
+ .WriteText(ASCIIToUTF16(text));
+}
+
} // namespace
namespace views {
@@ -237,20 +248,6 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
}
}
- base::string16 GetClipboardText() const {
- base::string16 text;
- ui::Clipboard::GetForCurrentThread()->
- ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &text);
- return text;
- }
-
- void SetClipboardText(const std::string& text) {
- ui::ScopedClipboardWriter clipboard_writer(
- ui::Clipboard::GetForCurrentThread(),
- ui::CLIPBOARD_TYPE_COPY_PASTE);
- clipboard_writer.WriteText(ASCIIToUTF16(text));
- }
-
View* GetFocusedView() {
return widget_->GetFocusManager()->GetFocusedView();
}
@@ -277,7 +274,7 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
// Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and
// y-axis is in the middle of |bound|'s vertical range.
void MouseClick(const gfx::Rect bound, int x_offset) {
- gfx::Point point(bound.x() + x_offset, bound.y() + bound.height() / 2);
+ gfx::Point point(bound.x() + x_offset, bound.y() + bound.height() / 2);
ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
textfield_->OnMousePressed(click);
@@ -298,11 +295,6 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
textfield_->OnMouseReleased(release);
}
- // Wrap for visibility in test classes.
- ui::TextInputType GetTextInputType() {
- return textfield_->GetTextInputType();
- }
-
void VerifyTextfieldContextMenuContents(bool textfield_has_selection,
bool can_undo,
ui::MenuModel* menu) {
@@ -310,7 +302,8 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
EXPECT_TRUE(menu->IsEnabledAt(1 /* Separator */));
EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(2 /* CUT */));
EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(3 /* COPY */));
- EXPECT_NE(GetClipboardText().empty(), menu->IsEnabledAt(4 /* PASTE */));
+ EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE).empty(),
+ menu->IsEnabledAt(4 /* PASTE */));
EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(5 /* DELETE */));
EXPECT_TRUE(menu->IsEnabledAt(6 /* Separator */));
EXPECT_TRUE(menu->IsEnabledAt(7 /* SELECT ALL */));
@@ -465,7 +458,7 @@ TEST_F(TextfieldTest, InsertionDeletionTest) {
TEST_F(TextfieldTest, PasswordTest) {
InitTextfield();
textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
EXPECT_TRUE(textfield_->enabled());
EXPECT_TRUE(textfield_->IsFocusable());
@@ -475,7 +468,7 @@ TEST_F(TextfieldTest, PasswordTest) {
EXPECT_STR_EQ("password", textfield_->text());
EXPECT_TRUE(last_contents_.empty());
model_->SelectAll(false);
- SetClipboardText("foo");
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
// Cut and copy should be disabled.
EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
@@ -485,7 +478,7 @@ TEST_F(TextfieldTest, PasswordTest) {
textfield_->ExecuteCommand(IDS_APP_COPY, 0);
SendKeyEvent(ui::VKEY_C, false, true);
SendKeyEvent(ui::VKEY_INSERT, false, true);
- EXPECT_STR_EQ("foo", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("password", textfield_->text());
// [Shift]+[Delete] should just delete without copying text to the clipboard.
textfield_->SelectAll(false);
@@ -496,7 +489,7 @@ TEST_F(TextfieldTest, PasswordTest) {
textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
SendKeyEvent(ui::VKEY_V, false, true);
SendKeyEvent(ui::VKEY_INSERT, true, false);
- EXPECT_STR_EQ("foo", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("foofoofoo", textfield_->text());
}
@@ -504,27 +497,27 @@ TEST_F(TextfieldTest, TextInputType) {
InitTextfield();
// Defaults to TEXT
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, textfield_->GetTextInputType());
// And can be set.
textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_URL);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, textfield_->GetTextInputType());
textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
// Readonly textfields have type NONE
textfield_->SetReadOnly(true);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
textfield_->SetReadOnly(false);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
// As do disabled textfields
textfield_->SetEnabled(false);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
textfield_->SetEnabled(true);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
}
TEST_F(TextfieldTest, OnKeyPressReturnValueTest) {
@@ -667,7 +660,7 @@ TEST_F(TextfieldTest, FocusTraversalTest) {
textfield_->RequestFocus();
EXPECT_EQ(1, GetFocusedView()->id());
- // Test if clicking on textfield view sets the focus to textfield_.
+ // Test if clicking on textfield view sets the focus.
widget_->GetFocusManager()->AdvanceFocus(true);
EXPECT_EQ(3, GetFocusedView()->id());
ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
@@ -695,7 +688,7 @@ TEST_F(TextfieldTest, ContextMenuDisplayTest) {
VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
// Exercise the "paste enabled?" check in the verifier.
- SetClipboardText("Test");
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
}
@@ -1026,12 +1019,12 @@ TEST_F(TextfieldTest, ReadOnlyTest) {
EXPECT_STR_EQ("read only", textfield_->GetSelectedText());
// Cut should be disabled.
- SetClipboardText("Test");
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
textfield_->ExecuteCommand(IDS_APP_CUT, 0);
SendKeyEvent(ui::VKEY_X, false, true);
SendKeyEvent(ui::VKEY_DELETE, true, false);
- EXPECT_STR_EQ("Test", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("read only", textfield_->text());
// Paste should be disabled.
@@ -1042,16 +1035,16 @@ TEST_F(TextfieldTest, ReadOnlyTest) {
EXPECT_STR_EQ("read only", textfield_->text());
// Copy should work normally.
- SetClipboardText("Test");
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
textfield_->ExecuteCommand(IDS_APP_COPY, 0);
- EXPECT_STR_EQ("read only", base::string16(GetClipboardText()));
- SetClipboardText("Test");
+ EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
SendKeyEvent(ui::VKEY_C, false, true);
- EXPECT_STR_EQ("read only", base::string16(GetClipboardText()));
- SetClipboardText("Test");
+ EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
SendKeyEvent(ui::VKEY_INSERT, false, true);
- EXPECT_STR_EQ("read only", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
// SetText should work even in read only mode.
textfield_->SetText(ASCIIToUTF16(" four five six "));
@@ -1276,24 +1269,24 @@ TEST_F(TextfieldTest, CutCopyPaste) {
textfield_->SelectAll(false);
EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
textfield_->ExecuteCommand(IDS_APP_CUT, 0);
- EXPECT_STR_EQ("123", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("", textfield_->text());
// Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
textfield_->SetText(ASCIIToUTF16("456"));
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_X, true, false, true, false);
- EXPECT_STR_EQ("123", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("456", textfield_->text());
SendKeyEvent(ui::VKEY_X, false, true);
- EXPECT_STR_EQ("456", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("", textfield_->text());
// Ensure [Shift]+[Delete] cuts.
textfield_->SetText(ASCIIToUTF16("123"));
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_DELETE, true, false);
- EXPECT_STR_EQ("123", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("", textfield_->text());
// Ensure IDS_APP_COPY copies.
@@ -1301,26 +1294,26 @@ TEST_F(TextfieldTest, CutCopyPaste) {
textfield_->SelectAll(false);
EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
textfield_->ExecuteCommand(IDS_APP_COPY, 0);
- EXPECT_STR_EQ("789", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
// Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
textfield_->SetText(ASCIIToUTF16("012"));
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_C, true, false, true, false);
- EXPECT_STR_EQ("789", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
SendKeyEvent(ui::VKEY_C, false, true);
- EXPECT_STR_EQ("012", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
// Ensure [Ctrl]+[Insert] copies.
textfield_->SetText(ASCIIToUTF16("345"));
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_INSERT, false, true);
- EXPECT_STR_EQ("345", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("345", textfield_->text());
// Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
// also ensure that [Ctrl]+[Alt]+[V] does nothing.
- SetClipboardText("abc");
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "abc");
textfield_->SetText(base::string16());
EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
@@ -1335,7 +1328,7 @@ TEST_F(TextfieldTest, CutCopyPaste) {
// Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_INSERT, true, true);
- EXPECT_STR_EQ("abc", base::string16(GetClipboardText()));
+ EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("abcabcabc", textfield_->text());
}
@@ -1747,6 +1740,109 @@ TEST_F(TextfieldTest, KeepInitiallySelectedWord) {
EXPECT_EQ(gfx::Range(7, 0), textfield_->GetSelectedRange());
}
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+TEST_F(TextfieldTest, SelectionClipboard) {
+ InitTextfield();
+ textfield_->SetText(ASCIIToUTF16("0123"));
+ gfx::Point point_1(GetCursorPositionX(1), 0);
+ gfx::Point point_2(GetCursorPositionX(2), 0);
+ gfx::Point point_3(GetCursorPositionX(3), 0);
+ gfx::Point point_4(GetCursorPositionX(4), 0);
+
+ // Text selected by the mouse should be placed on the selection clipboard.
+ ui::MouseEvent press(ui::ET_MOUSE_PRESSED, point_1, point_1,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(press);
+ ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, point_3, point_3,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMouseDragged(drag);
+ ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point_3, point_3,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMouseReleased(release);
+ EXPECT_EQ(gfx::Range(1, 3), textfield_->GetSelectedRange());
+ EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+
+ // Select-all should update the selection clipboard.
+ SendKeyEvent(ui::VKEY_A, false, true);
+ EXPECT_EQ(gfx::Range(0, 4), textfield_->GetSelectedRange());
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+
+ // Shift-click selection modifications should update the clipboard.
+ NonClientMouseClick();
+ ui::MouseEvent press_2(ui::ET_MOUSE_PRESSED, point_2, point_2,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ press_2.set_flags(press_2.flags() | ui::EF_SHIFT_DOWN);
+ textfield_->OnMousePressed(press_2);
+ ui::MouseEvent release_2(ui::ET_MOUSE_RELEASED, point_2, point_2,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMouseReleased(release_2);
+ EXPECT_EQ(gfx::Range(0, 2), textfield_->GetSelectedRange());
+ EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+
+ // Shift-Left/Right should update the selection clipboard.
+ SendKeyEvent(ui::VKEY_RIGHT, true, false);
+ EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ SendKeyEvent(ui::VKEY_LEFT, true, false);
+ EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ SendKeyEvent(ui::VKEY_RIGHT, true, true);
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+
+ // Moving the cursor without a selection should not change the clipboard.
+ SendKeyEvent(ui::VKEY_LEFT, false, false);
+ EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+
+ // Middle clicking should paste at the mouse (not cursor) location.
+ ui::MouseEvent middle(ui::ET_MOUSE_PRESSED, point_4, point_4,
+ ui::EF_MIDDLE_MOUSE_BUTTON, ui::EF_MIDDLE_MOUSE_BUTTON);
+ textfield_->OnMousePressed(middle);
+ EXPECT_STR_EQ("01230123", textfield_->text());
+ EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+
+ // Middle click pasting should adjust trailing cursors.
+ textfield_->SelectRange(gfx::Range(5, 5));
+ textfield_->OnMousePressed(middle);
+ EXPECT_STR_EQ("012301230123", textfield_->text());
+ EXPECT_EQ(gfx::Range(9, 9), textfield_->GetSelectedRange());
+
+ // Middle click pasting should adjust trailing selections.
+ textfield_->SelectRange(gfx::Range(7, 9));
+ textfield_->OnMousePressed(middle);
+ EXPECT_STR_EQ("0123012301230123", textfield_->text());
+ EXPECT_EQ(gfx::Range(11, 13), textfield_->GetSelectedRange());
+
+ // Middle clicking in the selection should clear the clipboard and selection.
+ textfield_->SelectRange(gfx::Range(2, 6));
+ textfield_->OnMousePressed(middle);
+ EXPECT_STR_EQ("0123012301230123", textfield_->text());
+ EXPECT_EQ(gfx::Range(6, 6), textfield_->GetSelectedRange());
+ EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
+
+ // Double and triple clicking should update the clipboard contents.
+ textfield_->SetText(ASCIIToUTF16("ab cd ef"));
+ gfx::Point word(GetCursorPositionX(4), 0);
+ ui::MouseEvent press_word(ui::ET_MOUSE_PRESSED, word, word,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(press_word);
+ ui::MouseEvent release_word(ui::ET_MOUSE_RELEASED, word, word,
+ ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMouseReleased(release_word);
+ ui::MouseEvent double_click(ui::ET_MOUSE_PRESSED, word, word,
+ ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(double_click);
+ textfield_->OnMouseReleased(release_word);
+ EXPECT_EQ(gfx::Range(3, 5), textfield_->GetSelectedRange());
+ EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ textfield_->OnMousePressed(press_word);
+ textfield_->OnMouseReleased(release_word);
+ EXPECT_EQ(gfx::Range(0, 8), textfield_->GetSelectedRange());
+ EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+}
+#endif
+
// Touch selection and dragging currently only works for chromeos.
#if defined(OS_CHROMEOS)
TEST_F(TextfieldTest, TouchSelectionAndDraggingTest) {