#include "base/win/win_util.h"
#endif
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#include "base/strings/utf_string_conversions.h"
+#include "ui/events/linux/text_edit_command_auralinux.h"
+#include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
+#endif
+
namespace views {
namespace {
// Default placeholder text color.
const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY;
+const int kNoCommand = 0;
+
void ConvertRectToScreen(const View* src, gfx::Rect* r) {
DCHECK(src);
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;
+}
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+int GetViewsCommand(const ui::TextEditCommandAuraLinux& command, bool rtl) {
+ const bool select = command.extend_selection();
+ switch (command.command_id()) {
+ case ui::TextEditCommandAuraLinux::COPY:
+ return IDS_APP_COPY;
+ case ui::TextEditCommandAuraLinux::CUT:
+ return IDS_APP_CUT;
+ case ui::TextEditCommandAuraLinux::DELETE_BACKWARD:
+ return IDS_DELETE_BACKWARD;
+ case ui::TextEditCommandAuraLinux::DELETE_FORWARD:
+ return IDS_DELETE_FORWARD;
+ case ui::TextEditCommandAuraLinux::DELETE_TO_BEGINING_OF_LINE:
+ case ui::TextEditCommandAuraLinux::DELETE_TO_BEGINING_OF_PARAGRAPH:
+ return IDS_DELETE_TO_BEGINNING_OF_LINE;
+ case ui::TextEditCommandAuraLinux::DELETE_TO_END_OF_LINE:
+ case ui::TextEditCommandAuraLinux::DELETE_TO_END_OF_PARAGRAPH:
+ return IDS_DELETE_TO_END_OF_LINE;
+ case ui::TextEditCommandAuraLinux::DELETE_WORD_BACKWARD:
+ return IDS_DELETE_WORD_BACKWARD;
+ case ui::TextEditCommandAuraLinux::DELETE_WORD_FORWARD:
+ return IDS_DELETE_WORD_FORWARD;
+ case ui::TextEditCommandAuraLinux::INSERT_TEXT:
+ return kNoCommand;
+ case ui::TextEditCommandAuraLinux::MOVE_BACKWARD:
+ if (rtl)
+ return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
+ return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
+ case ui::TextEditCommandAuraLinux::MOVE_DOWN:
+ return IDS_MOVE_DOWN;
+ case ui::TextEditCommandAuraLinux::MOVE_FORWARD:
+ if (rtl)
+ return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
+ return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
+ case ui::TextEditCommandAuraLinux::MOVE_LEFT:
+ return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
+ case ui::TextEditCommandAuraLinux::MOVE_PAGE_DOWN:
+ case ui::TextEditCommandAuraLinux::MOVE_PAGE_UP:
+ return kNoCommand;
+ case ui::TextEditCommandAuraLinux::MOVE_RIGHT:
+ return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
+ case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_DOCUMENT:
+ case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_LINE:
+ case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_PARAGRAPH:
+ return select ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
+ IDS_MOVE_TO_BEGINNING_OF_LINE;
+ case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_DOCUMENT:
+ case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_LINE:
+ case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_PARAGRAPH:
+ return select ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION :
+ IDS_MOVE_TO_END_OF_LINE;
+ case ui::TextEditCommandAuraLinux::MOVE_UP:
+ return IDS_MOVE_UP;
+ case ui::TextEditCommandAuraLinux::MOVE_WORD_BACKWARD:
+ if (rtl) {
+ return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_RIGHT;
+ }
+ return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_LEFT;
+ case ui::TextEditCommandAuraLinux::MOVE_WORD_FORWARD:
+ if (rtl) {
+ return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_LEFT;
+ }
+ return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_RIGHT;
+ case ui::TextEditCommandAuraLinux::MOVE_WORD_LEFT:
+ return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_LEFT;
+ case ui::TextEditCommandAuraLinux::MOVE_WORD_RIGHT:
+ return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_RIGHT;
+ case ui::TextEditCommandAuraLinux::PASTE:
+ return IDS_APP_PASTE;
+ case ui::TextEditCommandAuraLinux::SELECT_ALL:
+ return IDS_APP_SELECT_ALL;
+ case ui::TextEditCommandAuraLinux::SET_MARK:
+ case ui::TextEditCommandAuraLinux::UNSELECT:
+ case ui::TextEditCommandAuraLinux::INVALID_COMMAND:
+ return kNoCommand;
+ }
+ return kNoCommand;
+}
+#endif
+
} // namespace
// static
use_default_background_color_(true),
placeholder_text_color_(kDefaultPlaceholderTextColor),
text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
+ performing_user_action_(false),
skip_input_method_cancel_composition_(false),
cursor_visible_(false),
drop_cursor_visible_(false),
if (handled)
return true;
- // TODO(oshima): Refactor and consolidate with ExecuteCommand.
- if (event.type() == ui::ET_KEY_PRESSED) {
- ui::KeyboardCode key_code = event.key_code();
- if (key_code == ui::VKEY_TAB || event.IsUnicodeKeyCode())
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
+ ui::GetTextEditKeyBindingsDelegate();
+ std::vector<ui::TextEditCommandAuraLinux> commands;
+ if (delegate) {
+ if (!delegate->MatchEvent(event, &commands))
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;
+ const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
+ for (size_t i = 0; i < commands.size(); ++i) {
+ int command = GetViewsCommand(commands[i], rtl);
+ if (IsCommandIdEnabled(command)) {
+ ExecuteCommand(command);
+ handled = true;
}
- 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;
}
+ return handled;
+ }
+#endif
- // We must have input method in order to support text input.
- DCHECK(GetInputMethod());
- UpdateAfterChange(text_changed, cursor_changed);
- OnAfterUserAction();
- return (text_changed || cursor_changed);
+ const int command = GetCommandForKeyEvent(event, HasSelection());
+ if (IsCommandIdEnabled(command)) {
+ ExecuteCommand(command);
+ return true;
}
return false;
}
SelectAll(false);
}
-bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
+bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ // Skip any accelerator handling that conflicts with custom keybindings.
+ ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
+ ui::GetTextEditKeyBindingsDelegate();
+ std::vector<ui::TextEditCommandAuraLinux> commands;
+ if (delegate && delegate->MatchEvent(event, &commands)) {
+ const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
+ for (size_t i = 0; i < commands.size(); ++i)
+ if (IsCommandIdEnabled(GetViewsCommand(commands[i], rtl)))
+ return true;
+ }
+#endif
+
// Skip any accelerator handling of backspace; textfields handle this key.
// Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes.
- return e.key_code() == ui::VKEY_BACK || e.IsUnicodeKeyCode();
+ return event.key_code() == ui::VKEY_BACK || event.IsUnicodeKeyCode();
}
bool Textfield::GetDropFormats(
switch (command_id) {
case IDS_APP_UNDO:
return editable && model_->CanUndo();
+ case IDS_APP_REDO:
+ return editable && model_->CanRedo();
case IDS_APP_CUT:
return editable && readable && model_->HasSelection();
case IDS_APP_COPY:
return editable && model_->HasSelection();
case IDS_APP_SELECT_ALL:
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:
return false;
}
return;
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();
switch (command_id) {
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;
case IDS_APP_CUT:
- text_changed = Cut();
+ text_changed = cursor_changed = Cut();
break;
case IDS_APP_COPY:
Copy();
break;
case IDS_APP_PASTE:
- text_changed = Paste();
+ text_changed = cursor_changed = Paste();
break;
case IDS_APP_DELETE:
- text_changed = model_->Delete();
+ text_changed = cursor_changed = model_->Delete();
break;
case IDS_APP_SELECT_ALL:
SelectAll(false);
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:
NOTREACHED();
break;
}
- UpdateAfterChange(text_changed, text_changed);
+
+ cursor_changed |= GetSelectedRange() != selection_range;
+ if (cursor_changed)
+ UpdateSelectionClipboard();
+ UpdateAfterChange(text_changed, cursor_changed);
OnAfterUserAction();
}
}
void Textfield::OnBeforeUserAction() {
+ DCHECK(!performing_user_action_);
+ performing_user_action_ = true;
if (controller_)
controller_->OnBeforeUserAction(this);
}
void Textfield::OnAfterUserAction() {
if (controller_)
controller_->OnAfterUserAction(this);
+ DCHECK(performing_user_action_);
+ performing_user_action_ = false;
}
bool Textfield::Cut() {
if (!read_only() && text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD &&
model_->Cut()) {
if (controller_)
- controller_->OnAfterCutOrCopy();
+ controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_COPY_PASTE);
return true;
}
return false;
bool Textfield::Copy() {
if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD && model_->Copy()) {
if (controller_)
- controller_->OnAfterCutOrCopy();
+ controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_COPY_PASTE);
return true;
}
return false;
void Textfield::UpdateSelectionClipboard() const {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- if (HasSelection()) {
+ if (performing_user_action_ && HasSelection()) {
ui::ScopedClipboardWriter(
ui::Clipboard::GetForCurrentThread(),
ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText());
+ if (controller_)
+ controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
}
#endif
}