Commit f8ecc8d0 authored by msw@chromium.org's avatar msw@chromium.org

Make Views Textfield key handling execute commands.

Add commands similar to WebKit text editing commands.
Translate key events to commands for textfield execution.
Consolidate key handling and command execution code.
Fix unit tests.

Modify Windows behavior for CTRL+SHIFT+[BACK|DEL].
(now behaves the same as CTRL+[BACK|DEL], not no-op)

BUG=319437
TEST=No behavior changes except for CTRL+SHIFT+[BACK|DEL] on Windows.
R=oshima@chromium.org, erg@chromium.org

Review URL: https://codereview.chromium.org/211593006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260310 0039d316-1c4b-4281-b951-d872f2087c98
parent c7ae9787
...@@ -1878,7 +1878,7 @@ need to be translated for each locale.--> ...@@ -1878,7 +1878,7 @@ need to be translated for each locale.-->
Scroll Down Scroll Down
</message> </message>
<!-- Edit field context menu item labels. --> <!-- Textfield context menu item labels. -->
<message name="IDS_APP_UNDO" desc="The text label of the Undo menu item"> <message name="IDS_APP_UNDO" desc="The text label of the Undo menu item">
&amp;Undo &amp;Undo
</message> </message>
...@@ -1898,6 +1898,66 @@ need to be translated for each locale.--> ...@@ -1898,6 +1898,66 @@ need to be translated for each locale.-->
Select &amp;all Select &amp;all
</message> </message>
<!-- Textfield editing commands; their actual string contents are unused. -->
<!-- These match third_party/WebKit/Source/core/editing/EditorCommand.cpp. -->
<message name="IDS_DELETE_BACKWARD" desc="A command to delete backward.">
Delete Backward
</message>
<message name="IDS_DELETE_FORWARD" desc="A command to delete forward.">
Delete Forward
</message>
<message name="IDS_DELETE_TO_BEGINNING_OF_LINE" desc="A command to delete to the beginning of the line.">
Delete To Beginning Of Line
</message>
<message name="IDS_DELETE_TO_END_OF_LINE" desc="A command to delete to the end of the line.">
Delete To End Of Line
</message>
<message name="IDS_DELETE_WORD_BACKWARD" desc="A command to delete backward by a word.">
Delete Word Backward
</message>
<message name="IDS_DELETE_WORD_FORWARD" desc="A command to delete forward by a word.">
Delete Word Forward
</message>
<message name="IDS_MOVE_LEFT" desc="A command to move the cursor left.">
Move Left
</message>
<message name="IDS_MOVE_LEFT_AND_MODIFY_SELECTION" desc="A command to move the cursor left and modify the selection.">
Move Left And Modify Selection
</message>
<message name="IDS_MOVE_RIGHT" desc="A command to move the cursor right.">
Move Right
</message>
<message name="IDS_MOVE_RIGHT_AND_MODIFY_SELECTION" desc="A command to move the cursor right and modify the selection.">
Move Right And Modify Selection
</message>
<message name="IDS_MOVE_WORD_LEFT" desc="A command to move the cursor left to the next word break.">
Move Word Left
</message>
<message name="IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION" desc="A command to move the cursor left to the next word break and modify the selection.">
Move Word Left And Modify Selection
</message>
<message name="IDS_MOVE_WORD_RIGHT" desc="A command to move the cursor right to the next word break.">
Move Word Right
</message>
<message name="IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION" desc="A command to move the cursor right to the next word break and modify the selection.">
Move Word Right And Modify Selection
</message>
<message name="IDS_MOVE_TO_BEGINNING_OF_LINE" desc="A command to move the cursor to the beginning of the line.">
Move To Beginning Of Line
</message>
<message name="IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION" desc="A command to move the cursor to the beginning of the line and modify the selection.">
Move To Beginning Of Line And Modify Selection
</message>
<message name="IDS_MOVE_TO_END_OF_LINE" desc="A command to move the cursor to the end of the line.">
Move To End Of Line
</message>
<message name="IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION" desc="A command to move the cursor to the end of the line and modify the selection.">
Move To End Of Line And Modify Selection
</message>
<message name="IDS_APP_REDO" desc="A command to redo an action.">
Redo
</message>
<!-- Generic terms --> <!-- Generic terms -->
<message name="IDS_APP_OK" desc="Used for Ok on buttons"> <message name="IDS_APP_OK" desc="Used for Ok on buttons">
OK OK
......
...@@ -47,6 +47,8 @@ namespace { ...@@ -47,6 +47,8 @@ namespace {
// Default placeholder text color. // Default placeholder text color.
const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY; const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY;
const int kNoCommand = 0;
void ConvertRectToScreen(const View* src, gfx::Rect* r) { void ConvertRectToScreen(const View* src, gfx::Rect* r) {
DCHECK(src); DCHECK(src);
...@@ -55,6 +57,78 @@ void ConvertRectToScreen(const View* src, gfx::Rect* r) { ...@@ -55,6 +57,78 @@ void ConvertRectToScreen(const View* src, gfx::Rect* r) {
r->set_origin(new_origin); r->set_origin(new_origin);
} }
int GetCommandForKeyEvent(const ui::KeyEvent& event, bool has_selection) {
if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode())
return kNoCommand;
const bool shift = event.IsShiftDown();
const bool control = event.IsControlDown();
const bool alt = event.IsAltDown() || event.IsAltGrDown();
switch (event.key_code()) {
case ui::VKEY_Z:
if (control && !shift && !alt)
return IDS_APP_UNDO;
return (control && shift && !alt) ? IDS_APP_REDO : kNoCommand;
case ui::VKEY_Y:
return (control && !alt) ? IDS_APP_REDO : kNoCommand;
case ui::VKEY_A:
return (control && !alt) ? IDS_APP_SELECT_ALL : kNoCommand;
case ui::VKEY_X:
return (control && !alt) ? IDS_APP_CUT : kNoCommand;
case ui::VKEY_C:
return (control && !alt) ? IDS_APP_COPY : kNoCommand;
case ui::VKEY_V:
return (control && !alt) ? IDS_APP_PASTE : kNoCommand;
case ui::VKEY_RIGHT:
// Ignore alt+right, which may be a browser navigation shortcut.
if (alt)
return kNoCommand;
if (!shift)
return control ? IDS_MOVE_WORD_RIGHT : IDS_MOVE_RIGHT;
return control ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
IDS_MOVE_RIGHT_AND_MODIFY_SELECTION;
case ui::VKEY_LEFT:
// Ignore alt+left, which may be a browser navigation shortcut.
if (alt)
return kNoCommand;
if (!shift)
return control ? IDS_MOVE_WORD_LEFT : IDS_MOVE_LEFT;
return control ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
IDS_MOVE_LEFT_AND_MODIFY_SELECTION;
case ui::VKEY_HOME:
return shift ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
IDS_MOVE_TO_BEGINNING_OF_LINE;
case ui::VKEY_END:
return shift ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION :
IDS_MOVE_TO_END_OF_LINE;
case ui::VKEY_BACK:
if (!control || has_selection)
return IDS_DELETE_BACKWARD;
#if defined(OS_LINUX)
// Only erase by line break on Linux and ChromeOS.
if (shift)
return IDS_DELETE_TO_BEGINNING_OF_LINE;
#endif
return IDS_DELETE_WORD_BACKWARD;
case ui::VKEY_DELETE:
if (!control || has_selection)
return (shift && has_selection) ? IDS_APP_CUT : IDS_DELETE_FORWARD;
#if defined(OS_LINUX)
// Only erase by line break on Linux and ChromeOS.
if (shift)
return IDS_DELETE_TO_END_OF_LINE;
#endif
return IDS_DELETE_WORD_FORWARD;
case ui::VKEY_INSERT:
if (control && !shift)
return IDS_APP_COPY;
return (shift && !control) ? IDS_APP_PASTE : kNoCommand;
default:
return kNoCommand;
}
return kNoCommand;
}
} // namespace } // namespace
// static // static
...@@ -419,129 +493,15 @@ void Textfield::OnMouseReleased(const ui::MouseEvent& event) { ...@@ -419,129 +493,15 @@ void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
} }
bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
bool handled = controller_ && controller_->HandleKeyEvent(this, event); const bool handled = controller_ && controller_->HandleKeyEvent(this, event);
touch_selection_controller_.reset(); touch_selection_controller_.reset();
if (handled) if (handled)
return true; return true;
// TODO(oshima): Refactor and consolidate with ExecuteCommand. const int command = GetCommandForKeyEvent(event, HasSelection());
if (event.type() == ui::ET_KEY_PRESSED) { if (IsCommandIdEnabled(command)) {
ui::KeyboardCode key_code = event.key_code(); ExecuteCommand(command);
if (key_code == ui::VKEY_TAB || event.IsUnicodeKeyCode()) return true;
return false;
gfx::RenderText* render_text = GetRenderText();
const bool editable = !read_only();
const bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD;
const bool shift = event.IsShiftDown();
const bool control = event.IsControlDown();
const bool alt = event.IsAltDown() || event.IsAltGrDown();
bool text_changed = false;
bool cursor_changed = false;
OnBeforeUserAction();
switch (key_code) {
case ui::VKEY_Z:
if (control && !shift && !alt && editable)
cursor_changed = text_changed = model_->Undo();
else if (control && shift && !alt && editable)
cursor_changed = text_changed = model_->Redo();
break;
case ui::VKEY_Y:
if (control && !alt && editable)
cursor_changed = text_changed = model_->Redo();
break;
case ui::VKEY_A:
if (control && !alt) {
model_->SelectAll(false);
UpdateSelectionClipboard();
cursor_changed = true;
}
break;
case ui::VKEY_X:
if (control && !alt && editable && readable)
cursor_changed = text_changed = Cut();
break;
case ui::VKEY_C:
if (control && !alt && readable)
Copy();
break;
case ui::VKEY_V:
if (control && !alt && editable)
cursor_changed = text_changed = Paste();
break;
case ui::VKEY_RIGHT:
case ui::VKEY_LEFT: {
// We should ignore the alt-left/right keys because alt key doesn't make
// any special effects for them and they can be shortcut keys such like
// forward/back of the browser history.
if (alt)
break;
const gfx::Range selection_range = render_text->selection();
model_->MoveCursor(
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;
}
case ui::VKEY_END:
case ui::VKEY_HOME:
if ((key_code == ui::VKEY_HOME) ==
(render_text->GetTextDirection() == base::i18n::RIGHT_TO_LEFT))
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:
case ui::VKEY_DELETE:
if (!editable)
break;
if (!model_->HasSelection()) {
gfx::VisualCursorDirection direction = (key_code == ui::VKEY_DELETE) ?
gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
if (shift && control) {
// If shift and control are pressed, erase up to the next line break
// on Linux and ChromeOS. Otherwise, do nothing.
#if defined(OS_LINUX)
model_->MoveCursor(gfx::LINE_BREAK, direction, true);
#else
break;
#endif
} else if (control) {
// If only control is pressed, then erase the previous/next word.
model_->MoveCursor(gfx::WORD_BREAK, direction, true);
}
}
if (key_code == ui::VKEY_BACK)
model_->Backspace();
else if (shift && model_->HasSelection() && readable)
Cut();
else
model_->Delete();
// Consume backspace and delete keys even if the edit did nothing. This
// prevents potential unintended side-effects of further event handling.
text_changed = true;
break;
case ui::VKEY_INSERT:
if (control && !shift && readable)
Copy();
else if (shift && !control && editable)
cursor_changed = text_changed = Paste();
break;
default:
break;
}
// We must have input method in order to support text input.
DCHECK(GetInputMethod());
UpdateAfterChange(text_changed, cursor_changed);
OnAfterUserAction();
return (text_changed || cursor_changed);
} }
return false; return false;
} }
...@@ -960,6 +920,8 @@ bool Textfield::IsCommandIdEnabled(int command_id) const { ...@@ -960,6 +920,8 @@ bool Textfield::IsCommandIdEnabled(int command_id) const {
switch (command_id) { switch (command_id) {
case IDS_APP_UNDO: case IDS_APP_UNDO:
return editable && model_->CanUndo(); return editable && model_->CanUndo();
case IDS_APP_REDO:
return editable && model_->CanRedo();
case IDS_APP_CUT: case IDS_APP_CUT:
return editable && readable && model_->HasSelection(); return editable && readable && model_->HasSelection();
case IDS_APP_COPY: case IDS_APP_COPY:
...@@ -972,6 +934,26 @@ bool Textfield::IsCommandIdEnabled(int command_id) const { ...@@ -972,6 +934,26 @@ bool Textfield::IsCommandIdEnabled(int command_id) const {
return editable && model_->HasSelection(); return editable && model_->HasSelection();
case IDS_APP_SELECT_ALL: case IDS_APP_SELECT_ALL:
return !text().empty(); return !text().empty();
case IDS_DELETE_FORWARD:
case IDS_DELETE_BACKWARD:
case IDS_DELETE_TO_BEGINNING_OF_LINE:
case IDS_DELETE_TO_END_OF_LINE:
case IDS_DELETE_WORD_BACKWARD:
case IDS_DELETE_WORD_FORWARD:
return editable;
case IDS_MOVE_LEFT:
case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
case IDS_MOVE_RIGHT:
case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
case IDS_MOVE_WORD_LEFT:
case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
case IDS_MOVE_WORD_RIGHT:
case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
case IDS_MOVE_TO_BEGINNING_OF_LINE:
case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
case IDS_MOVE_TO_END_OF_LINE:
case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
return true;
default: default:
return false; return false;
} }
...@@ -988,31 +970,102 @@ void Textfield::ExecuteCommand(int command_id, int event_flags) { ...@@ -988,31 +970,102 @@ void Textfield::ExecuteCommand(int command_id, int event_flags) {
return; return;
bool text_changed = false; bool text_changed = false;
bool cursor_changed = false;
bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
gfx::VisualCursorDirection begin = rtl ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
gfx::VisualCursorDirection end = rtl ? gfx::CURSOR_LEFT : gfx::CURSOR_RIGHT;
gfx::Range selection_range = GetSelectedRange();
OnBeforeUserAction(); OnBeforeUserAction();
switch (command_id) { switch (command_id) {
case IDS_APP_UNDO: case IDS_APP_UNDO:
text_changed = model_->Undo(); text_changed = cursor_changed = model_->Undo();
break;
case IDS_APP_REDO:
text_changed = cursor_changed = model_->Redo();
break; break;
case IDS_APP_CUT: case IDS_APP_CUT:
text_changed = Cut(); text_changed = cursor_changed = Cut();
break; break;
case IDS_APP_COPY: case IDS_APP_COPY:
Copy(); Copy();
break; break;
case IDS_APP_PASTE: case IDS_APP_PASTE:
text_changed = Paste(); text_changed = cursor_changed = Paste();
break; break;
case IDS_APP_DELETE: case IDS_APP_DELETE:
text_changed = model_->Delete(); text_changed = cursor_changed = model_->Delete();
break; break;
case IDS_APP_SELECT_ALL: case IDS_APP_SELECT_ALL:
SelectAll(false); SelectAll(false);
break; break;
case IDS_DELETE_BACKWARD:
text_changed = cursor_changed = model_->Backspace();
break;
case IDS_DELETE_FORWARD:
text_changed = cursor_changed = model_->Delete();
break;
case IDS_DELETE_TO_END_OF_LINE:
model_->MoveCursor(gfx::LINE_BREAK, end, true);
text_changed = cursor_changed = model_->Delete();
break;
case IDS_DELETE_TO_BEGINNING_OF_LINE:
model_->MoveCursor(gfx::LINE_BREAK, begin, true);
text_changed = cursor_changed = model_->Backspace();
break;
case IDS_DELETE_WORD_BACKWARD:
model_->MoveCursor(gfx::WORD_BREAK, begin, true);
text_changed = cursor_changed = model_->Backspace();
break;
case IDS_DELETE_WORD_FORWARD:
model_->MoveCursor(gfx::WORD_BREAK, end, true);
text_changed = cursor_changed = model_->Delete();
break;
case IDS_MOVE_LEFT:
model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
break;
case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
break;
case IDS_MOVE_RIGHT:
model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
break;
case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
break;
case IDS_MOVE_WORD_LEFT:
model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
break;
case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
break;
case IDS_MOVE_WORD_RIGHT:
model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
break;
case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
break;
case IDS_MOVE_TO_BEGINNING_OF_LINE:
model_->MoveCursor(gfx::LINE_BREAK, begin, false);
break;
case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
model_->MoveCursor(gfx::LINE_BREAK, begin, true);
break;
case IDS_MOVE_TO_END_OF_LINE:
model_->MoveCursor(gfx::LINE_BREAK, end, false);
break;
case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
model_->MoveCursor(gfx::LINE_BREAK, end, true);
break;
default: default:
NOTREACHED(); NOTREACHED();
break; break;
} }
UpdateAfterChange(text_changed, text_changed);
cursor_changed |= GetSelectedRange() != selection_range;
if (cursor_changed)
UpdateSelectionClipboard();
UpdateAfterChange(text_changed, cursor_changed);
OnAfterUserAction(); OnAfterUserAction();
} }
......
...@@ -430,13 +430,13 @@ TEST_F(TextfieldTest, InsertionDeletionTest) { ...@@ -430,13 +430,13 @@ TEST_F(TextfieldTest, InsertionDeletionTest) {
SendKeyEvent(ui::VKEY_BACK, false, false, true, false); SendKeyEvent(ui::VKEY_BACK, false, false, true, false);
EXPECT_STR_EQ("one two three ", textfield_->text()); EXPECT_STR_EQ("one two three ", textfield_->text());
// Delete to a line break on Linux and ChromeOS, no-op on Windows. // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
SendKeyEvent(ui::VKEY_LEFT, false, false, true, false); SendKeyEvent(ui::VKEY_LEFT, false, false, true, false);
SendKeyEvent(ui::VKEY_BACK, false, true, true, false); SendKeyEvent(ui::VKEY_BACK, false, true, true, false);
#if defined(OS_LINUX) #if defined(OS_LINUX)
EXPECT_STR_EQ("three ", textfield_->text()); EXPECT_STR_EQ("three ", textfield_->text());
#else #else
EXPECT_STR_EQ("one two three ", textfield_->text()); EXPECT_STR_EQ("one three ", textfield_->text());
#endif #endif
// Delete the next word from cursor. // Delete the next word from cursor.
...@@ -445,13 +445,13 @@ TEST_F(TextfieldTest, InsertionDeletionTest) { ...@@ -445,13 +445,13 @@ TEST_F(TextfieldTest, InsertionDeletionTest) {
SendKeyEvent(ui::VKEY_DELETE, false, false, true, false); SendKeyEvent(ui::VKEY_DELETE, false, false, true, false);
EXPECT_STR_EQ(" two three four", textfield_->text()); EXPECT_STR_EQ(" two three four", textfield_->text());
// Delete to a line break on Linux and ChromeOS, no-op on Windows. // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
SendKeyEvent(ui::VKEY_RIGHT, false, false, true, false); SendKeyEvent(ui::VKEY_RIGHT, false, false, true, false);
SendKeyEvent(ui::VKEY_DELETE, false, true, true, false); SendKeyEvent(ui::VKEY_DELETE, false, true, true, false);
#if defined(OS_LINUX) #if defined(OS_LINUX)
EXPECT_STR_EQ(" two", textfield_->text()); EXPECT_STR_EQ(" two", textfield_->text());
#else #else
EXPECT_STR_EQ(" two three four", textfield_->text()); EXPECT_STR_EQ(" two four", textfield_->text());
#endif #endif
} }
...@@ -523,61 +523,45 @@ TEST_F(TextfieldTest, TextInputType) { ...@@ -523,61 +523,45 @@ TEST_F(TextfieldTest, TextInputType) {
TEST_F(TextfieldTest, OnKeyPressReturnValueTest) { TEST_F(TextfieldTest, OnKeyPressReturnValueTest) {
InitTextfield(); InitTextfield();
// Character keys will be handled by input method. // Character keys are handled by the input method.
SendKeyEvent(ui::VKEY_A); SendKeyEvent(ui::VKEY_A);
EXPECT_TRUE(textfield_->key_received()); EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled()); EXPECT_FALSE(textfield_->key_handled());
textfield_->clear(); textfield_->clear();
// Home will be handled. // Arrow keys and home/end are handled by the textfield.
SendKeyEvent(ui::VKEY_HOME); SendKeyEvent(ui::VKEY_LEFT);
EXPECT_TRUE(textfield_->key_received()); EXPECT_TRUE(textfield_->key_received());
EXPECT_TRUE(textfield_->key_handled()); EXPECT_TRUE(textfield_->key_handled());
textfield_->clear(); textfield_->clear();
// F24, up/down key won't be handled. SendKeyEvent(ui::VKEY_RIGHT);
SendKeyEvent(ui::VKEY_F24);
EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled());
textfield_->clear();
SendKeyEvent(ui::VKEY_UP);
EXPECT_TRUE(textfield_->key_received()); EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled()); EXPECT_TRUE(textfield_->key_handled());
textfield_->clear(); textfield_->clear();
SendKeyEvent(ui::VKEY_DOWN); SendKeyEvent(ui::VKEY_HOME);
EXPECT_TRUE(textfield_->key_received()); EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled()); EXPECT_TRUE(textfield_->key_handled());
textfield_->clear(); textfield_->clear();
// Empty Textfield does not handle left/right. SendKeyEvent(ui::VKEY_END);
textfield_->SetText(base::string16());
SendKeyEvent(ui::VKEY_LEFT);
EXPECT_TRUE(textfield_->key_received()); EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled()); EXPECT_TRUE(textfield_->key_handled());
textfield_->clear(); textfield_->clear();
SendKeyEvent(ui::VKEY_RIGHT); // F24, up/down key won't be handled.
SendKeyEvent(ui::VKEY_F24);
EXPECT_TRUE(textfield_->key_received()); EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled()); EXPECT_FALSE(textfield_->key_handled());
textfield_->clear(); textfield_->clear();
// Add a char. Right key should not be handled when cursor is at the end. SendKeyEvent(ui::VKEY_UP);
SendKeyEvent(ui::VKEY_B);
SendKeyEvent(ui::VKEY_RIGHT);
EXPECT_TRUE(textfield_->key_received()); EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled()); EXPECT_FALSE(textfield_->key_handled());
textfield_->clear(); textfield_->clear();
// First left key is handled to move cursor left to the beginning. SendKeyEvent(ui::VKEY_DOWN);
SendKeyEvent(ui::VKEY_LEFT);
EXPECT_TRUE(textfield_->key_received());
EXPECT_TRUE(textfield_->key_handled());
textfield_->clear();
// Now left key should not be handled.
SendKeyEvent(ui::VKEY_LEFT);
EXPECT_TRUE(textfield_->key_received()); EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled()); EXPECT_FALSE(textfield_->key_handled());
textfield_->clear(); textfield_->clear();
...@@ -1106,8 +1090,8 @@ TEST_F(TextfieldTest, TextInputClientTest) { ...@@ -1106,8 +1090,8 @@ TEST_F(TextfieldTest, TextInputClientTest) {
EXPECT_TRUE(client->GetCompositionTextRange(&range)); EXPECT_TRUE(client->GetCompositionTextRange(&range));
EXPECT_STR_EQ("0321456789", textfield_->text()); EXPECT_STR_EQ("0321456789", textfield_->text());
EXPECT_EQ(gfx::Range(1, 4), range); EXPECT_EQ(gfx::Range(1, 4), range);
EXPECT_EQ(2, on_before_user_action_); EXPECT_EQ(1, on_before_user_action_);
EXPECT_EQ(2, on_after_user_action_); EXPECT_EQ(1, on_after_user_action_);
input_method_->SetResultTextForNextKey(UTF8ToUTF16("123")); input_method_->SetResultTextForNextKey(UTF8ToUTF16("123"));
on_before_user_action_ = on_after_user_action_ = 0; on_before_user_action_ = on_after_user_action_ = 0;
...@@ -1118,8 +1102,8 @@ TEST_F(TextfieldTest, TextInputClientTest) { ...@@ -1118,8 +1102,8 @@ TEST_F(TextfieldTest, TextInputClientTest) {
EXPECT_FALSE(client->HasCompositionText()); EXPECT_FALSE(client->HasCompositionText());
EXPECT_FALSE(input_method_->cancel_composition_called()); EXPECT_FALSE(input_method_->cancel_composition_called());
EXPECT_STR_EQ("0123456789", textfield_->text()); EXPECT_STR_EQ("0123456789", textfield_->text());
EXPECT_EQ(2, on_before_user_action_); EXPECT_EQ(1, on_before_user_action_);
EXPECT_EQ(2, on_after_user_action_); EXPECT_EQ(1, on_after_user_action_);
input_method_->Clear(); input_method_->Clear();
input_method_->SetCompositionTextForNextKey(composition); input_method_->SetCompositionTextForNextKey(composition);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment