Home | History | Annotate | Download | only in textfield
      1 // Copyright (c) 2012 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 <string>
      8 
      9 #include "base/debug/trace_event.h"
     10 #include "grit/ui_strings.h"
     11 #include "ui/accessibility/ax_view_state.h"
     12 #include "ui/base/clipboard/scoped_clipboard_writer.h"
     13 #include "ui/base/cursor/cursor.h"
     14 #include "ui/base/dragdrop/drag_drop_types.h"
     15 #include "ui/base/dragdrop/drag_utils.h"
     16 #include "ui/base/resource/resource_bundle.h"
     17 #include "ui/base/ui_base_switches_util.h"
     18 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
     19 #include "ui/events/event.h"
     20 #include "ui/events/keycodes/keyboard_codes.h"
     21 #include "ui/gfx/canvas.h"
     22 #include "ui/gfx/display.h"
     23 #include "ui/gfx/insets.h"
     24 #include "ui/gfx/screen.h"
     25 #include "ui/native_theme/native_theme.h"
     26 #include "ui/views/background.h"
     27 #include "ui/views/controls/focusable_border.h"
     28 #include "ui/views/controls/label.h"
     29 #include "ui/views/controls/menu/menu_runner.h"
     30 #include "ui/views/controls/native/native_view_host.h"
     31 #include "ui/views/controls/textfield/textfield_controller.h"
     32 #include "ui/views/drag_utils.h"
     33 #include "ui/views/ime/input_method.h"
     34 #include "ui/views/metrics.h"
     35 #include "ui/views/native_cursor.h"
     36 #include "ui/views/painter.h"
     37 #include "ui/views/views_delegate.h"
     38 #include "ui/views/widget/widget.h"
     39 
     40 #if defined(OS_WIN)
     41 #include "base/win/win_util.h"
     42 #endif
     43 
     44 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
     45 #include "base/strings/utf_string_conversions.h"
     46 #include "ui/events/linux/text_edit_command_auralinux.h"
     47 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
     48 #endif
     49 
     50 namespace views {
     51 
     52 namespace {
     53 
     54 // Default placeholder text color.
     55 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY;
     56 
     57 const int kNoCommand = 0;
     58 
     59 void ConvertRectToScreen(const View* src, gfx::Rect* r) {
     60   DCHECK(src);
     61 
     62   gfx::Point new_origin = r->origin();
     63   View::ConvertPointToScreen(src, &new_origin);
     64   r->set_origin(new_origin);
     65 }
     66 
     67 // Get the drag selection timer delay, respecting animation scaling for testing.
     68 int GetDragSelectionDelay() {
     69   switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) {
     70       case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: return 100;
     71       case ui::ScopedAnimationDurationScaleMode::FAST_DURATION:   return 25;
     72       case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION:   return 400;
     73       case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION:   return 0;
     74     }
     75   return 100;
     76 }
     77 
     78 // Get the default command for a given key |event| and selection state.
     79 int GetCommandForKeyEvent(const ui::KeyEvent& event, bool has_selection) {
     80   if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode())
     81     return kNoCommand;
     82 
     83   const bool shift = event.IsShiftDown();
     84   const bool control = event.IsControlDown();
     85   const bool alt = event.IsAltDown() || event.IsAltGrDown();
     86   switch (event.key_code()) {
     87     case ui::VKEY_Z:
     88       if (control && !shift && !alt)
     89         return IDS_APP_UNDO;
     90       return (control && shift && !alt) ? IDS_APP_REDO : kNoCommand;
     91     case ui::VKEY_Y:
     92       return (control && !alt) ? IDS_APP_REDO : kNoCommand;
     93     case ui::VKEY_A:
     94       return (control && !alt) ? IDS_APP_SELECT_ALL : kNoCommand;
     95     case ui::VKEY_X:
     96       return (control && !alt) ? IDS_APP_CUT : kNoCommand;
     97     case ui::VKEY_C:
     98       return (control && !alt) ? IDS_APP_COPY : kNoCommand;
     99     case ui::VKEY_V:
    100       return (control && !alt) ? IDS_APP_PASTE : kNoCommand;
    101     case ui::VKEY_RIGHT:
    102       // Ignore alt+right, which may be a browser navigation shortcut.
    103       if (alt)
    104         return kNoCommand;
    105       if (!shift)
    106         return control ? IDS_MOVE_WORD_RIGHT : IDS_MOVE_RIGHT;
    107       return control ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
    108                         IDS_MOVE_RIGHT_AND_MODIFY_SELECTION;
    109     case ui::VKEY_LEFT:
    110       // Ignore alt+left, which may be a browser navigation shortcut.
    111       if (alt)
    112         return kNoCommand;
    113       if (!shift)
    114         return control ? IDS_MOVE_WORD_LEFT : IDS_MOVE_LEFT;
    115       return control ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
    116                         IDS_MOVE_LEFT_AND_MODIFY_SELECTION;
    117     case ui::VKEY_HOME:
    118       return shift ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
    119                       IDS_MOVE_TO_BEGINNING_OF_LINE;
    120     case ui::VKEY_END:
    121       return shift ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION :
    122                       IDS_MOVE_TO_END_OF_LINE;
    123     case ui::VKEY_BACK:
    124       if (!control || has_selection)
    125         return IDS_DELETE_BACKWARD;
    126 #if defined(OS_LINUX)
    127       // Only erase by line break on Linux and ChromeOS.
    128       if (shift)
    129         return IDS_DELETE_TO_BEGINNING_OF_LINE;
    130 #endif
    131       return IDS_DELETE_WORD_BACKWARD;
    132     case ui::VKEY_DELETE:
    133       if (!control || has_selection)
    134         return (shift && has_selection) ? IDS_APP_CUT : IDS_DELETE_FORWARD;
    135 #if defined(OS_LINUX)
    136       // Only erase by line break on Linux and ChromeOS.
    137       if (shift)
    138         return IDS_DELETE_TO_END_OF_LINE;
    139 #endif
    140       return IDS_DELETE_WORD_FORWARD;
    141     case ui::VKEY_INSERT:
    142       if (control && !shift)
    143         return IDS_APP_COPY;
    144       return (shift && !control) ? IDS_APP_PASTE : kNoCommand;
    145     default:
    146       return kNoCommand;
    147   }
    148 }
    149 
    150 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
    151 // Convert a custom text edit |command| to the equivalent views command ID.
    152 int GetViewsCommand(const ui::TextEditCommandAuraLinux& command, bool rtl) {
    153   const bool select = command.extend_selection();
    154   switch (command.command_id()) {
    155     case ui::TextEditCommandAuraLinux::COPY:
    156       return IDS_APP_COPY;
    157     case ui::TextEditCommandAuraLinux::CUT:
    158       return IDS_APP_CUT;
    159     case ui::TextEditCommandAuraLinux::DELETE_BACKWARD:
    160       return IDS_DELETE_BACKWARD;
    161     case ui::TextEditCommandAuraLinux::DELETE_FORWARD:
    162       return IDS_DELETE_FORWARD;
    163     case ui::TextEditCommandAuraLinux::DELETE_TO_BEGINING_OF_LINE:
    164     case ui::TextEditCommandAuraLinux::DELETE_TO_BEGINING_OF_PARAGRAPH:
    165       return IDS_DELETE_TO_BEGINNING_OF_LINE;
    166     case ui::TextEditCommandAuraLinux::DELETE_TO_END_OF_LINE:
    167     case ui::TextEditCommandAuraLinux::DELETE_TO_END_OF_PARAGRAPH:
    168       return IDS_DELETE_TO_END_OF_LINE;
    169     case ui::TextEditCommandAuraLinux::DELETE_WORD_BACKWARD:
    170       return IDS_DELETE_WORD_BACKWARD;
    171     case ui::TextEditCommandAuraLinux::DELETE_WORD_FORWARD:
    172       return IDS_DELETE_WORD_FORWARD;
    173     case ui::TextEditCommandAuraLinux::INSERT_TEXT:
    174       return kNoCommand;
    175     case ui::TextEditCommandAuraLinux::MOVE_BACKWARD:
    176       if (rtl)
    177         return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
    178       return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
    179     case ui::TextEditCommandAuraLinux::MOVE_DOWN:
    180       return IDS_MOVE_DOWN;
    181     case ui::TextEditCommandAuraLinux::MOVE_FORWARD:
    182       if (rtl)
    183         return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
    184       return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
    185     case ui::TextEditCommandAuraLinux::MOVE_LEFT:
    186       return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
    187     case ui::TextEditCommandAuraLinux::MOVE_PAGE_DOWN:
    188     case ui::TextEditCommandAuraLinux::MOVE_PAGE_UP:
    189       return kNoCommand;
    190     case ui::TextEditCommandAuraLinux::MOVE_RIGHT:
    191       return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
    192     case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_DOCUMENT:
    193     case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_LINE:
    194     case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_PARAGRAPH:
    195       return select ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
    196                       IDS_MOVE_TO_BEGINNING_OF_LINE;
    197     case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_DOCUMENT:
    198     case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_LINE:
    199     case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_PARAGRAPH:
    200       return select ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION :
    201                       IDS_MOVE_TO_END_OF_LINE;
    202     case ui::TextEditCommandAuraLinux::MOVE_UP:
    203       return IDS_MOVE_UP;
    204     case ui::TextEditCommandAuraLinux::MOVE_WORD_BACKWARD:
    205       if (rtl) {
    206         return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
    207                         IDS_MOVE_WORD_RIGHT;
    208       }
    209       return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
    210                       IDS_MOVE_WORD_LEFT;
    211     case ui::TextEditCommandAuraLinux::MOVE_WORD_FORWARD:
    212       if (rtl) {
    213         return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
    214                         IDS_MOVE_WORD_LEFT;
    215       }
    216       return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
    217                       IDS_MOVE_WORD_RIGHT;
    218     case ui::TextEditCommandAuraLinux::MOVE_WORD_LEFT:
    219       return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
    220                       IDS_MOVE_WORD_LEFT;
    221     case ui::TextEditCommandAuraLinux::MOVE_WORD_RIGHT:
    222       return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
    223                       IDS_MOVE_WORD_RIGHT;
    224     case ui::TextEditCommandAuraLinux::PASTE:
    225       return IDS_APP_PASTE;
    226     case ui::TextEditCommandAuraLinux::SELECT_ALL:
    227       return IDS_APP_SELECT_ALL;
    228     case ui::TextEditCommandAuraLinux::SET_MARK:
    229     case ui::TextEditCommandAuraLinux::UNSELECT:
    230     case ui::TextEditCommandAuraLinux::INVALID_COMMAND:
    231       return kNoCommand;
    232   }
    233   return kNoCommand;
    234 }
    235 #endif
    236 
    237 }  // namespace
    238 
    239 // static
    240 const char Textfield::kViewClassName[] = "Textfield";
    241 
    242 // static
    243 size_t Textfield::GetCaretBlinkMs() {
    244   static const size_t default_value = 500;
    245 #if defined(OS_WIN)
    246   static const size_t system_value = ::GetCaretBlinkTime();
    247   if (system_value != 0)
    248     return (system_value == INFINITE) ? 0 : system_value;
    249 #endif
    250   return default_value;
    251 }
    252 
    253 Textfield::Textfield()
    254     : model_(new TextfieldModel(this)),
    255       controller_(NULL),
    256       read_only_(false),
    257       default_width_in_chars_(0),
    258       use_default_text_color_(true),
    259       use_default_background_color_(true),
    260       use_default_selection_text_color_(true),
    261       use_default_selection_background_color_(true),
    262       text_color_(SK_ColorBLACK),
    263       background_color_(SK_ColorWHITE),
    264       selection_text_color_(SK_ColorWHITE),
    265       selection_background_color_(SK_ColorBLUE),
    266       placeholder_text_color_(kDefaultPlaceholderTextColor),
    267       text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
    268       performing_user_action_(false),
    269       skip_input_method_cancel_composition_(false),
    270       cursor_visible_(false),
    271       drop_cursor_visible_(false),
    272       initiating_drag_(false),
    273       aggregated_clicks_(0),
    274       weak_ptr_factory_(this) {
    275   set_context_menu_controller(this);
    276   set_drag_controller(this);
    277   SetBorder(scoped_ptr<Border>(new FocusableBorder()));
    278   SetFocusable(true);
    279 
    280   if (ViewsDelegate::views_delegate) {
    281     password_reveal_duration_ = ViewsDelegate::views_delegate->
    282         GetDefaultTextfieldObscuredRevealDuration();
    283   }
    284 }
    285 
    286 Textfield::~Textfield() {}
    287 
    288 void Textfield::SetReadOnly(bool read_only) {
    289   // Update read-only without changing the focusable state (or active, etc.).
    290   read_only_ = read_only;
    291   if (GetInputMethod())
    292     GetInputMethod()->OnTextInputTypeChanged(this);
    293   SetColor(GetTextColor());
    294   UpdateBackgroundColor();
    295 }
    296 
    297 void Textfield::SetTextInputType(ui::TextInputType type) {
    298   GetRenderText()->SetObscured(type == ui::TEXT_INPUT_TYPE_PASSWORD);
    299   text_input_type_ = type;
    300   OnCaretBoundsChanged();
    301   if (GetInputMethod())
    302     GetInputMethod()->OnTextInputTypeChanged(this);
    303   SchedulePaint();
    304 }
    305 
    306 void Textfield::SetText(const base::string16& new_text) {
    307   model_->SetText(new_text);
    308   OnCaretBoundsChanged();
    309   SchedulePaint();
    310   NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
    311 }
    312 
    313 void Textfield::AppendText(const base::string16& new_text) {
    314   if (new_text.empty())
    315     return;
    316   model_->Append(new_text);
    317   OnCaretBoundsChanged();
    318   SchedulePaint();
    319 }
    320 
    321 void Textfield::InsertOrReplaceText(const base::string16& new_text) {
    322   if (new_text.empty())
    323     return;
    324   model_->InsertText(new_text);
    325   OnCaretBoundsChanged();
    326   SchedulePaint();
    327 }
    328 
    329 base::i18n::TextDirection Textfield::GetTextDirection() const {
    330   return GetRenderText()->GetTextDirection();
    331 }
    332 
    333 base::string16 Textfield::GetSelectedText() const {
    334   return model_->GetSelectedText();
    335 }
    336 
    337 void Textfield::SelectAll(bool reversed) {
    338   model_->SelectAll(reversed);
    339   UpdateSelectionClipboard();
    340   UpdateAfterChange(false, true);
    341 }
    342 
    343 void Textfield::ClearSelection() {
    344   model_->ClearSelection();
    345   UpdateAfterChange(false, true);
    346 }
    347 
    348 bool Textfield::HasSelection() const {
    349   return !GetSelectedRange().is_empty();
    350 }
    351 
    352 SkColor Textfield::GetTextColor() const {
    353   if (!use_default_text_color_)
    354     return text_color_;
    355 
    356   return GetNativeTheme()->GetSystemColor(read_only() ?
    357       ui::NativeTheme::kColorId_TextfieldReadOnlyColor :
    358       ui::NativeTheme::kColorId_TextfieldDefaultColor);
    359 }
    360 
    361 void Textfield::SetTextColor(SkColor color) {
    362   text_color_ = color;
    363   use_default_text_color_ = false;
    364   SetColor(color);
    365 }
    366 
    367 void Textfield::UseDefaultTextColor() {
    368   use_default_text_color_ = true;
    369   SetColor(GetTextColor());
    370 }
    371 
    372 SkColor Textfield::GetBackgroundColor() const {
    373   if (!use_default_background_color_)
    374     return background_color_;
    375 
    376   return GetNativeTheme()->GetSystemColor(read_only() ?
    377       ui::NativeTheme::kColorId_TextfieldReadOnlyBackground :
    378       ui::NativeTheme::kColorId_TextfieldDefaultBackground);
    379 }
    380 
    381 void Textfield::SetBackgroundColor(SkColor color) {
    382   background_color_ = color;
    383   use_default_background_color_ = false;
    384   UpdateBackgroundColor();
    385 }
    386 
    387 void Textfield::UseDefaultBackgroundColor() {
    388   use_default_background_color_ = true;
    389   UpdateBackgroundColor();
    390 }
    391 
    392 SkColor Textfield::GetSelectionTextColor() const {
    393   return use_default_selection_text_color_ ?
    394       GetNativeTheme()->GetSystemColor(
    395           ui::NativeTheme::kColorId_TextfieldSelectionColor) :
    396       selection_text_color_;
    397 }
    398 
    399 void Textfield::SetSelectionTextColor(SkColor color) {
    400   selection_text_color_ = color;
    401   use_default_selection_text_color_ = false;
    402   GetRenderText()->set_selection_color(GetSelectionTextColor());
    403   SchedulePaint();
    404 }
    405 
    406 void Textfield::UseDefaultSelectionTextColor() {
    407   use_default_selection_text_color_ = true;
    408   GetRenderText()->set_selection_color(GetSelectionTextColor());
    409   SchedulePaint();
    410 }
    411 
    412 SkColor Textfield::GetSelectionBackgroundColor() const {
    413   return use_default_selection_background_color_ ?
    414       GetNativeTheme()->GetSystemColor(
    415           ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused) :
    416       selection_background_color_;
    417 }
    418 
    419 void Textfield::SetSelectionBackgroundColor(SkColor color) {
    420   selection_background_color_ = color;
    421   use_default_selection_background_color_ = false;
    422   GetRenderText()->set_selection_background_focused_color(
    423       GetSelectionBackgroundColor());
    424   SchedulePaint();
    425 }
    426 
    427 void Textfield::UseDefaultSelectionBackgroundColor() {
    428   use_default_selection_background_color_ = true;
    429   GetRenderText()->set_selection_background_focused_color(
    430       GetSelectionBackgroundColor());
    431   SchedulePaint();
    432 }
    433 
    434 bool Textfield::GetCursorEnabled() const {
    435   return GetRenderText()->cursor_enabled();
    436 }
    437 
    438 void Textfield::SetCursorEnabled(bool enabled) {
    439   GetRenderText()->SetCursorEnabled(enabled);
    440 }
    441 
    442 const gfx::FontList& Textfield::GetFontList() const {
    443   return GetRenderText()->font_list();
    444 }
    445 
    446 void Textfield::SetFontList(const gfx::FontList& font_list) {
    447   GetRenderText()->SetFontList(font_list);
    448   OnCaretBoundsChanged();
    449   PreferredSizeChanged();
    450 }
    451 
    452 base::string16 Textfield::GetPlaceholderText() const {
    453   return placeholder_text_;
    454 }
    455 
    456 gfx::HorizontalAlignment Textfield::GetHorizontalAlignment() const {
    457   return GetRenderText()->horizontal_alignment();
    458 }
    459 
    460 void Textfield::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
    461   GetRenderText()->SetHorizontalAlignment(alignment);
    462 }
    463 
    464 void Textfield::ShowImeIfNeeded() {
    465   if (enabled() && !read_only())
    466     GetInputMethod()->ShowImeIfNeeded();
    467 }
    468 
    469 bool Textfield::IsIMEComposing() const {
    470   return model_->HasCompositionText();
    471 }
    472 
    473 const gfx::Range& Textfield::GetSelectedRange() const {
    474   return GetRenderText()->selection();
    475 }
    476 
    477 void Textfield::SelectRange(const gfx::Range& range) {
    478   model_->SelectRange(range);
    479   UpdateAfterChange(false, true);
    480 }
    481 
    482 const gfx::SelectionModel& Textfield::GetSelectionModel() const {
    483   return GetRenderText()->selection_model();
    484 }
    485 
    486 void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) {
    487   model_->SelectSelectionModel(sel);
    488   UpdateAfterChange(false, true);
    489 }
    490 
    491 size_t Textfield::GetCursorPosition() const {
    492   return model_->GetCursorPosition();
    493 }
    494 
    495 void Textfield::SetColor(SkColor value) {
    496   GetRenderText()->SetColor(value);
    497   SchedulePaint();
    498 }
    499 
    500 void Textfield::ApplyColor(SkColor value, const gfx::Range& range) {
    501   GetRenderText()->ApplyColor(value, range);
    502   SchedulePaint();
    503 }
    504 
    505 void Textfield::SetStyle(gfx::TextStyle style, bool value) {
    506   GetRenderText()->SetStyle(style, value);
    507   SchedulePaint();
    508 }
    509 
    510 void Textfield::ApplyStyle(gfx::TextStyle style,
    511                            bool value,
    512                            const gfx::Range& range) {
    513   GetRenderText()->ApplyStyle(style, value, range);
    514   SchedulePaint();
    515 }
    516 
    517 void Textfield::ClearEditHistory() {
    518   model_->ClearEditHistory();
    519 }
    520 
    521 void Textfield::SetAccessibleName(const base::string16& name) {
    522   accessible_name_ = name;
    523 }
    524 
    525 void Textfield::ExecuteCommand(int command_id) {
    526   ExecuteCommand(command_id, ui::EF_NONE);
    527 }
    528 
    529 void Textfield::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
    530   focus_painter_ = focus_painter.Pass();
    531 }
    532 
    533 bool Textfield::HasTextBeingDragged() {
    534   return initiating_drag_;
    535 }
    536 
    537 ////////////////////////////////////////////////////////////////////////////////
    538 // Textfield, View overrides:
    539 
    540 int Textfield::GetBaseline() const {
    541   return GetInsets().top() + GetRenderText()->GetBaseline();
    542 }
    543 
    544 gfx::Size Textfield::GetPreferredSize() const {
    545   const gfx::Insets& insets = GetInsets();
    546   return gfx::Size(GetFontList().GetExpectedTextWidth(default_width_in_chars_) +
    547                    insets.width(), GetFontList().GetHeight() + insets.height());
    548 }
    549 
    550 const char* Textfield::GetClassName() const {
    551   return kViewClassName;
    552 }
    553 
    554 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) {
    555   bool in_selection = GetRenderText()->IsPointInSelection(event.location());
    556   bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
    557   bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
    558   return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor;
    559 }
    560 
    561 bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
    562   TrackMouseClicks(event);
    563 
    564   if (!controller_ || !controller_->HandleMouseEvent(this, event)) {
    565     if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) {
    566       RequestFocus();
    567       ShowImeIfNeeded();
    568     }
    569 
    570     if (event.IsOnlyLeftMouseButton()) {
    571       OnBeforeUserAction();
    572       initiating_drag_ = false;
    573       switch (aggregated_clicks_) {
    574         case 0:
    575           if (GetRenderText()->IsPointInSelection(event.location()))
    576             initiating_drag_ = true;
    577           else
    578             MoveCursorTo(event.location(), event.IsShiftDown());
    579           break;
    580         case 1:
    581           model_->MoveCursorTo(event.location(), false);
    582           model_->SelectWord();
    583           UpdateAfterChange(false, true);
    584           double_click_word_ = GetRenderText()->selection();
    585           break;
    586         case 2:
    587           SelectAll(false);
    588           break;
    589         default:
    590           NOTREACHED();
    591       }
    592       OnAfterUserAction();
    593     }
    594 
    595 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
    596     if (event.IsOnlyMiddleMouseButton()) {
    597       if (GetRenderText()->IsPointInSelection(event.location())) {
    598         OnBeforeUserAction();
    599         ClearSelection();
    600         ui::ScopedClipboardWriter(
    601             ui::Clipboard::GetForCurrentThread(),
    602             ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16());
    603         OnAfterUserAction();
    604       } else if(!read_only()) {
    605         PasteSelectionClipboard(event);
    606       }
    607     }
    608 #endif
    609   }
    610 
    611   return true;
    612 }
    613 
    614 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
    615   last_drag_location_ = event.location();
    616 
    617   // Don't adjust the cursor on a potential drag and drop, or if the mouse
    618   // movement from the last mouse click does not exceed the drag threshold.
    619   if (initiating_drag_ || !event.IsOnlyLeftMouseButton() ||
    620       !ExceededDragThreshold(last_drag_location_ - last_click_location_)) {
    621     return true;
    622   }
    623 
    624   // A timer is used to continuously scroll while selecting beyond side edges.
    625   if ((event.location().x() > 0 && event.location().x() < size().width()) ||
    626       GetDragSelectionDelay() == 0) {
    627     drag_selection_timer_.Stop();
    628     SelectThroughLastDragLocation();
    629   } else if (!drag_selection_timer_.IsRunning()) {
    630     drag_selection_timer_.Start(
    631         FROM_HERE, base::TimeDelta::FromMilliseconds(GetDragSelectionDelay()),
    632         this, &Textfield::SelectThroughLastDragLocation);
    633   }
    634 
    635   return true;
    636 }
    637 
    638 void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
    639   OnBeforeUserAction();
    640   drag_selection_timer_.Stop();
    641   // Cancel suspected drag initiations, the user was clicking in the selection.
    642   if (initiating_drag_)
    643     MoveCursorTo(event.location(), false);
    644   initiating_drag_ = false;
    645   UpdateSelectionClipboard();
    646   OnAfterUserAction();
    647 }
    648 
    649 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
    650   bool handled = controller_ && controller_->HandleKeyEvent(this, event);
    651 
    652 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
    653   ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
    654       ui::GetTextEditKeyBindingsDelegate();
    655   std::vector<ui::TextEditCommandAuraLinux> commands;
    656   if (!handled && delegate && delegate->MatchEvent(event, &commands)) {
    657     const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
    658     for (size_t i = 0; i < commands.size(); ++i) {
    659       const int command = GetViewsCommand(commands[i], rtl);
    660       if (IsCommandIdEnabled(command)) {
    661         ExecuteCommand(command);
    662         handled = true;
    663       }
    664     }
    665     return handled;
    666   }
    667 #endif
    668 
    669   const int command = GetCommandForKeyEvent(event, HasSelection());
    670   if (!handled && IsCommandIdEnabled(command)) {
    671     ExecuteCommand(command);
    672     handled = true;
    673   }
    674   return handled;
    675 }
    676 
    677 ui::TextInputClient* Textfield::GetTextInputClient() {
    678   return read_only_ ? NULL : this;
    679 }
    680 
    681 void Textfield::OnGestureEvent(ui::GestureEvent* event) {
    682   switch (event->type()) {
    683     case ui::ET_GESTURE_TAP_DOWN:
    684       OnBeforeUserAction();
    685       RequestFocus();
    686       ShowImeIfNeeded();
    687 
    688       // We don't deselect if the point is in the selection
    689       // because TAP_DOWN may turn into a LONG_PRESS.
    690       if (!GetRenderText()->IsPointInSelection(event->location()))
    691         MoveCursorTo(event->location(), false);
    692       OnAfterUserAction();
    693       event->SetHandled();
    694       break;
    695     case ui::ET_GESTURE_SCROLL_UPDATE:
    696       OnBeforeUserAction();
    697       MoveCursorTo(event->location(), true);
    698       OnAfterUserAction();
    699       event->SetHandled();
    700       break;
    701     case ui::ET_GESTURE_SCROLL_END:
    702     case ui::ET_SCROLL_FLING_START:
    703       CreateTouchSelectionControllerAndNotifyIt();
    704       event->SetHandled();
    705       break;
    706     case ui::ET_GESTURE_TAP:
    707       if (event->details().tap_count() == 1) {
    708         CreateTouchSelectionControllerAndNotifyIt();
    709       } else {
    710         DestroyTouchSelection();
    711         OnBeforeUserAction();
    712         SelectAll(false);
    713         OnAfterUserAction();
    714         event->SetHandled();
    715       }
    716 #if defined(OS_WIN)
    717       if (!read_only())
    718         base::win::DisplayVirtualKeyboard();
    719 #endif
    720       break;
    721     case ui::ET_GESTURE_LONG_PRESS:
    722       // If long press happens outside selection, select word and show context
    723       // menu (If touch selection is enabled, context menu is shown by the
    724       // |touch_selection_controller_|, hence we mark the event handled.
    725       // Otherwise, the regular context menu will be shown by views).
    726       // If long press happens in selected text and touch drag drop is enabled,
    727       // we will turn off touch selection (if one exists) and let views do drag
    728       // drop.
    729       if (!GetRenderText()->IsPointInSelection(event->location())) {
    730         OnBeforeUserAction();
    731         model_->SelectWord();
    732         touch_selection_controller_.reset(
    733             ui::TouchSelectionController::create(this));
    734         UpdateAfterChange(false, true);
    735         OnAfterUserAction();
    736         if (touch_selection_controller_)
    737           event->SetHandled();
    738       } else if (switches::IsTouchDragDropEnabled()) {
    739         initiating_drag_ = true;
    740         DestroyTouchSelection();
    741       } else {
    742         if (!touch_selection_controller_)
    743           CreateTouchSelectionControllerAndNotifyIt();
    744         if (touch_selection_controller_)
    745           event->SetHandled();
    746       }
    747       return;
    748     case ui::ET_GESTURE_LONG_TAP:
    749       if (!touch_selection_controller_)
    750         CreateTouchSelectionControllerAndNotifyIt();
    751 
    752       // If touch selection is enabled, the context menu on long tap will be
    753       // shown by the |touch_selection_controller_|, hence we mark the event
    754       // handled so views does not try to show context menu on it.
    755       if (touch_selection_controller_)
    756         event->SetHandled();
    757       break;
    758     default:
    759       return;
    760   }
    761 }
    762 
    763 void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
    764   SelectAll(false);
    765 }
    766 
    767 bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
    768 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
    769   // Skip any accelerator handling that conflicts with custom keybindings.
    770   ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
    771       ui::GetTextEditKeyBindingsDelegate();
    772   std::vector<ui::TextEditCommandAuraLinux> commands;
    773   if (delegate && delegate->MatchEvent(event, &commands)) {
    774     const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
    775     for (size_t i = 0; i < commands.size(); ++i)
    776       if (IsCommandIdEnabled(GetViewsCommand(commands[i], rtl)))
    777         return true;
    778   }
    779 #endif
    780 
    781   // Skip backspace accelerator handling; editable textfields handle this key.
    782   // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes.
    783   const bool is_backspace = event.key_code() == ui::VKEY_BACK;
    784   return (is_backspace && !read_only()) || event.IsUnicodeKeyCode();
    785 }
    786 
    787 bool Textfield::GetDropFormats(
    788     int* formats,
    789     std::set<OSExchangeData::CustomFormat>* custom_formats) {
    790   if (!enabled() || read_only())
    791     return false;
    792   // TODO(msw): Can we support URL, FILENAME, etc.?
    793   *formats = ui::OSExchangeData::STRING;
    794   if (controller_)
    795     controller_->AppendDropFormats(formats, custom_formats);
    796   return true;
    797 }
    798 
    799 bool Textfield::CanDrop(const OSExchangeData& data) {
    800   int formats;
    801   std::set<OSExchangeData::CustomFormat> custom_formats;
    802   GetDropFormats(&formats, &custom_formats);
    803   return enabled() && !read_only() &&
    804       data.HasAnyFormat(formats, custom_formats);
    805 }
    806 
    807 int Textfield::OnDragUpdated(const ui::DropTargetEvent& event) {
    808   DCHECK(CanDrop(event.data()));
    809   gfx::RenderText* render_text = GetRenderText();
    810   const gfx::Range& selection = render_text->selection();
    811   drop_cursor_position_ = render_text->FindCursorPosition(event.location());
    812   bool in_selection = !selection.is_empty() &&
    813       selection.Contains(gfx::Range(drop_cursor_position_.caret_pos()));
    814   drop_cursor_visible_ = !in_selection;
    815   // TODO(msw): Pan over text when the user drags to the visible text edge.
    816   OnCaretBoundsChanged();
    817   SchedulePaint();
    818 
    819   if (initiating_drag_) {
    820     if (in_selection)
    821       return ui::DragDropTypes::DRAG_NONE;
    822     return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY :
    823                                    ui::DragDropTypes::DRAG_MOVE;
    824   }
    825   return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
    826 }
    827 
    828 void Textfield::OnDragExited() {
    829   drop_cursor_visible_ = false;
    830   SchedulePaint();
    831 }
    832 
    833 int Textfield::OnPerformDrop(const ui::DropTargetEvent& event) {
    834   DCHECK(CanDrop(event.data()));
    835   drop_cursor_visible_ = false;
    836 
    837   if (controller_) {
    838     int drag_operation = controller_->OnDrop(event.data());
    839     if (drag_operation != ui::DragDropTypes::DRAG_NONE)
    840       return drag_operation;
    841   }
    842 
    843   gfx::RenderText* render_text = GetRenderText();
    844   DCHECK(!initiating_drag_ ||
    845          !render_text->IsPointInSelection(event.location()));
    846   OnBeforeUserAction();
    847   skip_input_method_cancel_composition_ = true;
    848 
    849   gfx::SelectionModel drop_destination_model =
    850       render_text->FindCursorPosition(event.location());
    851   base::string16 new_text;
    852   event.data().GetString(&new_text);
    853 
    854   // Delete the current selection for a drag and drop within this view.
    855   const bool move = initiating_drag_ && !event.IsControlDown() &&
    856                     event.source_operations() & ui::DragDropTypes::DRAG_MOVE;
    857   if (move) {
    858     // Adjust the drop destination if it is on or after the current selection.
    859     size_t pos = drop_destination_model.caret_pos();
    860     pos -= render_text->selection().Intersect(gfx::Range(0, pos)).length();
    861     model_->DeleteSelectionAndInsertTextAt(new_text, pos);
    862   } else {
    863     model_->MoveCursorTo(drop_destination_model);
    864     // Drop always inserts text even if the textfield is not in insert mode.
    865     model_->InsertText(new_text);
    866   }
    867   skip_input_method_cancel_composition_ = false;
    868   UpdateAfterChange(true, true);
    869   OnAfterUserAction();
    870   return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY;
    871 }
    872 
    873 void Textfield::OnDragDone() {
    874   initiating_drag_ = false;
    875   drop_cursor_visible_ = false;
    876 }
    877 
    878 void Textfield::GetAccessibleState(ui::AXViewState* state) {
    879   state->role = ui::AX_ROLE_TEXT_FIELD;
    880   state->name = accessible_name_;
    881   if (read_only())
    882     state->AddStateFlag(ui::AX_STATE_READ_ONLY);
    883   if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD)
    884     state->AddStateFlag(ui::AX_STATE_PROTECTED);
    885   state->value = text();
    886 
    887   const gfx::Range range = GetSelectedRange();
    888   state->selection_start = range.start();
    889   state->selection_end = range.end();
    890 
    891   if (!read_only()) {
    892     state->set_value_callback =
    893         base::Bind(&Textfield::AccessibilitySetValue,
    894                    weak_ptr_factory_.GetWeakPtr());
    895   }
    896 }
    897 
    898 void Textfield::OnBoundsChanged(const gfx::Rect& previous_bounds) {
    899   GetRenderText()->SetDisplayRect(GetContentsBounds());
    900   OnCaretBoundsChanged();
    901 }
    902 
    903 void Textfield::OnEnabledChanged() {
    904   View::OnEnabledChanged();
    905   if (GetInputMethod())
    906     GetInputMethod()->OnTextInputTypeChanged(this);
    907   SchedulePaint();
    908 }
    909 
    910 void Textfield::OnPaint(gfx::Canvas* canvas) {
    911   OnPaintBackground(canvas);
    912   PaintTextAndCursor(canvas);
    913   OnPaintBorder(canvas);
    914 }
    915 
    916 void Textfield::OnFocus() {
    917   GetRenderText()->set_focused(true);
    918   cursor_visible_ = true;
    919   SchedulePaint();
    920   GetInputMethod()->OnFocus();
    921   OnCaretBoundsChanged();
    922 
    923   const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
    924   if (caret_blink_ms != 0) {
    925     cursor_repaint_timer_.Start(FROM_HERE,
    926         base::TimeDelta::FromMilliseconds(caret_blink_ms), this,
    927         &Textfield::UpdateCursor);
    928   }
    929 
    930   View::OnFocus();
    931   SchedulePaint();
    932 }
    933 
    934 void Textfield::OnBlur() {
    935   GetRenderText()->set_focused(false);
    936   GetInputMethod()->OnBlur();
    937   cursor_repaint_timer_.Stop();
    938   if (cursor_visible_) {
    939     cursor_visible_ = false;
    940     RepaintCursor();
    941   }
    942 
    943   DestroyTouchSelection();
    944 
    945   // Border typically draws focus indicator.
    946   SchedulePaint();
    947 }
    948 
    949 gfx::Point Textfield::GetKeyboardContextMenuLocation() {
    950   return GetCaretBounds().bottom_right();
    951 }
    952 
    953 void Textfield::OnNativeThemeChanged(const ui::NativeTheme* theme) {
    954   gfx::RenderText* render_text = GetRenderText();
    955   render_text->SetColor(GetTextColor());
    956   UpdateBackgroundColor();
    957   render_text->set_cursor_color(GetTextColor());
    958   render_text->set_selection_color(GetSelectionTextColor());
    959   render_text->set_selection_background_focused_color(
    960       GetSelectionBackgroundColor());
    961 }
    962 
    963 ////////////////////////////////////////////////////////////////////////////////
    964 // Textfield, TextfieldModel::Delegate overrides:
    965 
    966 void Textfield::OnCompositionTextConfirmedOrCleared() {
    967   if (!skip_input_method_cancel_composition_)
    968     GetInputMethod()->CancelComposition(this);
    969 }
    970 
    971 ////////////////////////////////////////////////////////////////////////////////
    972 // Textfield, ContextMenuController overrides:
    973 
    974 void Textfield::ShowContextMenuForView(View* source,
    975                                        const gfx::Point& point,
    976                                        ui::MenuSourceType source_type) {
    977   UpdateContextMenu();
    978   ignore_result(context_menu_runner_->RunMenuAt(
    979       GetWidget(),
    980       NULL,
    981       gfx::Rect(point, gfx::Size()),
    982       MENU_ANCHOR_TOPLEFT,
    983       source_type,
    984       MenuRunner::HAS_MNEMONICS | MenuRunner::CONTEXT_MENU));
    985 }
    986 
    987 ////////////////////////////////////////////////////////////////////////////////
    988 // Textfield, DragController overrides:
    989 
    990 void Textfield::WriteDragDataForView(View* sender,
    991                                      const gfx::Point& press_pt,
    992                                      OSExchangeData* data) {
    993   const base::string16& selected_text(GetSelectedText());
    994   data->SetString(selected_text);
    995   Label label(selected_text, GetFontList());
    996   label.SetBackgroundColor(GetBackgroundColor());
    997   label.set_subpixel_rendering_enabled(false);
    998   gfx::Size size(label.GetPreferredSize());
    999   gfx::NativeView native_view = GetWidget()->GetNativeView();
   1000   gfx::Display display = gfx::Screen::GetScreenFor(native_view)->
   1001       GetDisplayNearestWindow(native_view);
   1002   size.SetToMin(gfx::Size(display.size().width(), height()));
   1003   label.SetBoundsRect(gfx::Rect(size));
   1004   scoped_ptr<gfx::Canvas> canvas(
   1005       GetCanvasForDragImage(GetWidget(), label.size()));
   1006   label.SetEnabledColor(GetTextColor());
   1007 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
   1008   // Desktop Linux Aura does not yet support transparency in drag images.
   1009   canvas->DrawColor(GetBackgroundColor());
   1010 #endif
   1011   label.Paint(canvas.get(), views::CullSet());
   1012   const gfx::Vector2d kOffset(-15, 0);
   1013   drag_utils::SetDragImageOnDataObject(*canvas, kOffset, data);
   1014   if (controller_)
   1015     controller_->OnWriteDragData(data);
   1016 }
   1017 
   1018 int Textfield::GetDragOperationsForView(View* sender, const gfx::Point& p) {
   1019   int drag_operations = ui::DragDropTypes::DRAG_COPY;
   1020   if (!enabled() || text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD ||
   1021       !GetRenderText()->IsPointInSelection(p)) {
   1022     drag_operations = ui::DragDropTypes::DRAG_NONE;
   1023   } else if (sender == this && !read_only()) {
   1024     drag_operations =
   1025         ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY;
   1026   }
   1027   if (controller_)
   1028     controller_->OnGetDragOperationsForTextfield(&drag_operations);
   1029   return drag_operations;
   1030 }
   1031 
   1032 bool Textfield::CanStartDragForView(View* sender,
   1033                                     const gfx::Point& press_pt,
   1034                                     const gfx::Point& p) {
   1035   return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt);
   1036 }
   1037 
   1038 ////////////////////////////////////////////////////////////////////////////////
   1039 // Textfield, ui::TouchEditable overrides:
   1040 
   1041 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) {
   1042   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
   1043     return;
   1044 
   1045   gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start);
   1046   gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end);
   1047   gfx::SelectionModel selection(
   1048       gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()),
   1049       end_caret.caret_affinity());
   1050 
   1051   OnBeforeUserAction();
   1052   SelectSelectionModel(selection);
   1053   OnAfterUserAction();
   1054 }
   1055 
   1056 void Textfield::MoveCaretTo(const gfx::Point& point) {
   1057   SelectRect(point, point);
   1058 }
   1059 
   1060 void Textfield::GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) {
   1061   gfx::RenderText* render_text = GetRenderText();
   1062   const gfx::SelectionModel& sel = render_text->selection_model();
   1063   gfx::SelectionModel start_sel =
   1064       render_text->GetSelectionModelForSelectionStart();
   1065   *p1 = render_text->GetCursorBounds(start_sel, true);
   1066   *p2 = render_text->GetCursorBounds(sel, true);
   1067 }
   1068 
   1069 gfx::Rect Textfield::GetBounds() {
   1070   return GetLocalBounds();
   1071 }
   1072 
   1073 gfx::NativeView Textfield::GetNativeView() const {
   1074   return GetWidget()->GetNativeView();
   1075 }
   1076 
   1077 void Textfield::ConvertPointToScreen(gfx::Point* point) {
   1078   View::ConvertPointToScreen(this, point);
   1079 }
   1080 
   1081 void Textfield::ConvertPointFromScreen(gfx::Point* point) {
   1082   View::ConvertPointFromScreen(this, point);
   1083 }
   1084 
   1085 bool Textfield::DrawsHandles() {
   1086   return false;
   1087 }
   1088 
   1089 void Textfield::OpenContextMenu(const gfx::Point& anchor) {
   1090   DestroyTouchSelection();
   1091   ShowContextMenu(anchor, ui::MENU_SOURCE_TOUCH_EDIT_MENU);
   1092 }
   1093 
   1094 void Textfield::DestroyTouchSelection() {
   1095   touch_selection_controller_.reset();
   1096 }
   1097 
   1098 ////////////////////////////////////////////////////////////////////////////////
   1099 // Textfield, ui::SimpleMenuModel::Delegate overrides:
   1100 
   1101 bool Textfield::IsCommandIdChecked(int command_id) const {
   1102   return true;
   1103 }
   1104 
   1105 bool Textfield::IsCommandIdEnabled(int command_id) const {
   1106   base::string16 result;
   1107   bool editable = !read_only();
   1108   bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD;
   1109   switch (command_id) {
   1110     case IDS_APP_UNDO:
   1111       return editable && model_->CanUndo();
   1112     case IDS_APP_REDO:
   1113       return editable && model_->CanRedo();
   1114     case IDS_APP_CUT:
   1115       return editable && readable && model_->HasSelection();
   1116     case IDS_APP_COPY:
   1117       return readable && model_->HasSelection();
   1118     case IDS_APP_PASTE:
   1119       ui::Clipboard::GetForCurrentThread()->ReadText(
   1120           ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
   1121       return editable && !result.empty();
   1122     case IDS_APP_DELETE:
   1123       return editable && model_->HasSelection();
   1124     case IDS_APP_SELECT_ALL:
   1125       return !text().empty();
   1126     case IDS_DELETE_FORWARD:
   1127     case IDS_DELETE_BACKWARD:
   1128     case IDS_DELETE_TO_BEGINNING_OF_LINE:
   1129     case IDS_DELETE_TO_END_OF_LINE:
   1130     case IDS_DELETE_WORD_BACKWARD:
   1131     case IDS_DELETE_WORD_FORWARD:
   1132       return editable;
   1133     case IDS_MOVE_LEFT:
   1134     case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
   1135     case IDS_MOVE_RIGHT:
   1136     case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
   1137     case IDS_MOVE_WORD_LEFT:
   1138     case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
   1139     case IDS_MOVE_WORD_RIGHT:
   1140     case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
   1141     case IDS_MOVE_TO_BEGINNING_OF_LINE:
   1142     case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
   1143     case IDS_MOVE_TO_END_OF_LINE:
   1144     case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
   1145       return true;
   1146     default:
   1147       return false;
   1148   }
   1149 }
   1150 
   1151 bool Textfield::GetAcceleratorForCommandId(int command_id,
   1152                                            ui::Accelerator* accelerator) {
   1153   return false;
   1154 }
   1155 
   1156 void Textfield::ExecuteCommand(int command_id, int event_flags) {
   1157   DestroyTouchSelection();
   1158   if (!IsCommandIdEnabled(command_id))
   1159     return;
   1160 
   1161   bool text_changed = false;
   1162   bool cursor_changed = false;
   1163   bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
   1164   gfx::VisualCursorDirection begin = rtl ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
   1165   gfx::VisualCursorDirection end = rtl ? gfx::CURSOR_LEFT : gfx::CURSOR_RIGHT;
   1166   gfx::SelectionModel selection_model = GetSelectionModel();
   1167 
   1168   OnBeforeUserAction();
   1169   switch (command_id) {
   1170     case IDS_APP_UNDO:
   1171       text_changed = cursor_changed = model_->Undo();
   1172       break;
   1173     case IDS_APP_REDO:
   1174       text_changed = cursor_changed = model_->Redo();
   1175       break;
   1176     case IDS_APP_CUT:
   1177       text_changed = cursor_changed = Cut();
   1178       break;
   1179     case IDS_APP_COPY:
   1180       Copy();
   1181       break;
   1182     case IDS_APP_PASTE:
   1183       text_changed = cursor_changed = Paste();
   1184       break;
   1185     case IDS_APP_DELETE:
   1186       text_changed = cursor_changed = model_->Delete();
   1187       break;
   1188     case IDS_APP_SELECT_ALL:
   1189       SelectAll(false);
   1190       break;
   1191     case IDS_DELETE_BACKWARD:
   1192       text_changed = cursor_changed = model_->Backspace();
   1193       break;
   1194     case IDS_DELETE_FORWARD:
   1195       text_changed = cursor_changed = model_->Delete();
   1196       break;
   1197     case IDS_DELETE_TO_END_OF_LINE:
   1198       model_->MoveCursor(gfx::LINE_BREAK, end, true);
   1199       text_changed = cursor_changed = model_->Delete();
   1200       break;
   1201     case IDS_DELETE_TO_BEGINNING_OF_LINE:
   1202       model_->MoveCursor(gfx::LINE_BREAK, begin, true);
   1203       text_changed = cursor_changed = model_->Backspace();
   1204       break;
   1205     case IDS_DELETE_WORD_BACKWARD:
   1206       model_->MoveCursor(gfx::WORD_BREAK, begin, true);
   1207       text_changed = cursor_changed = model_->Backspace();
   1208       break;
   1209     case IDS_DELETE_WORD_FORWARD:
   1210       model_->MoveCursor(gfx::WORD_BREAK, end, true);
   1211       text_changed = cursor_changed = model_->Delete();
   1212       break;
   1213     case IDS_MOVE_LEFT:
   1214       model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
   1215       break;
   1216     case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
   1217       model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
   1218       break;
   1219     case IDS_MOVE_RIGHT:
   1220       model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
   1221       break;
   1222     case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
   1223       model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
   1224       break;
   1225     case IDS_MOVE_WORD_LEFT:
   1226       model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
   1227       break;
   1228     case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
   1229       model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
   1230       break;
   1231     case IDS_MOVE_WORD_RIGHT:
   1232       model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
   1233       break;
   1234     case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
   1235       model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
   1236       break;
   1237     case IDS_MOVE_TO_BEGINNING_OF_LINE:
   1238       model_->MoveCursor(gfx::LINE_BREAK, begin, false);
   1239       break;
   1240     case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
   1241       model_->MoveCursor(gfx::LINE_BREAK, begin, true);
   1242       break;
   1243     case IDS_MOVE_TO_END_OF_LINE:
   1244       model_->MoveCursor(gfx::LINE_BREAK, end, false);
   1245       break;
   1246     case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
   1247       model_->MoveCursor(gfx::LINE_BREAK, end, true);
   1248       break;
   1249     default:
   1250       NOTREACHED();
   1251       break;
   1252   }
   1253 
   1254   cursor_changed |= GetSelectionModel() != selection_model;
   1255   if (cursor_changed)
   1256     UpdateSelectionClipboard();
   1257   UpdateAfterChange(text_changed, cursor_changed);
   1258   OnAfterUserAction();
   1259 }
   1260 
   1261 ////////////////////////////////////////////////////////////////////////////////
   1262 // Textfield, ui::TextInputClient overrides:
   1263 
   1264 void Textfield::SetCompositionText(const ui::CompositionText& composition) {
   1265   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
   1266     return;
   1267 
   1268   OnBeforeUserAction();
   1269   skip_input_method_cancel_composition_ = true;
   1270   model_->SetCompositionText(composition);
   1271   skip_input_method_cancel_composition_ = false;
   1272   UpdateAfterChange(true, true);
   1273   OnAfterUserAction();
   1274 }
   1275 
   1276 void Textfield::ConfirmCompositionText() {
   1277   if (!model_->HasCompositionText())
   1278     return;
   1279 
   1280   OnBeforeUserAction();
   1281   skip_input_method_cancel_composition_ = true;
   1282   model_->ConfirmCompositionText();
   1283   skip_input_method_cancel_composition_ = false;
   1284   UpdateAfterChange(true, true);
   1285   OnAfterUserAction();
   1286 }
   1287 
   1288 void Textfield::ClearCompositionText() {
   1289   if (!model_->HasCompositionText())
   1290     return;
   1291 
   1292   OnBeforeUserAction();
   1293   skip_input_method_cancel_composition_ = true;
   1294   model_->CancelCompositionText();
   1295   skip_input_method_cancel_composition_ = false;
   1296   UpdateAfterChange(true, true);
   1297   OnAfterUserAction();
   1298 }
   1299 
   1300 void Textfield::InsertText(const base::string16& new_text) {
   1301   // TODO(suzhe): Filter invalid characters.
   1302   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || new_text.empty())
   1303     return;
   1304 
   1305   OnBeforeUserAction();
   1306   skip_input_method_cancel_composition_ = true;
   1307   if (GetRenderText()->insert_mode())
   1308     model_->InsertText(new_text);
   1309   else
   1310     model_->ReplaceText(new_text);
   1311   skip_input_method_cancel_composition_ = false;
   1312   UpdateAfterChange(true, true);
   1313   OnAfterUserAction();
   1314 }
   1315 
   1316 void Textfield::InsertChar(base::char16 ch, int flags) {
   1317   const int kControlModifierMask = ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
   1318                                    ui::EF_COMMAND_DOWN | ui::EF_ALTGR_DOWN |
   1319                                    ui::EF_MOD3_DOWN;
   1320 
   1321   // Filter out all control characters, including tab and new line characters,
   1322   // and all characters with Alt modifier. But allow characters with the AltGr
   1323   // modifier. On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a
   1324   // different flag that we don't care about.
   1325   const bool should_insert_char =
   1326       ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) &&
   1327       (flags & kControlModifierMask) != ui::EF_ALT_DOWN;
   1328   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || !should_insert_char)
   1329     return;
   1330 
   1331   OnBeforeUserAction();
   1332   skip_input_method_cancel_composition_ = true;
   1333   if (GetRenderText()->insert_mode())
   1334     model_->InsertChar(ch);
   1335   else
   1336     model_->ReplaceChar(ch);
   1337   skip_input_method_cancel_composition_ = false;
   1338 
   1339   UpdateAfterChange(true, true);
   1340   OnAfterUserAction();
   1341 
   1342   if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD &&
   1343       password_reveal_duration_ != base::TimeDelta()) {
   1344     const size_t change_offset = model_->GetCursorPosition();
   1345     DCHECK_GT(change_offset, 0u);
   1346     RevealPasswordChar(change_offset - 1);
   1347   }
   1348 }
   1349 
   1350 gfx::NativeWindow Textfield::GetAttachedWindow() const {
   1351   // Imagine the following hierarchy.
   1352   //   [NativeWidget A] - FocusManager
   1353   //     [View]
   1354   //     [NativeWidget B]
   1355   //       [View]
   1356   //         [View X]
   1357   // An important thing is that [NativeWidget A] owns Win32 input focus even
   1358   // when [View X] is logically focused by FocusManager. As a result, an Win32
   1359   // IME may want to interact with the native view of [NativeWidget A] rather
   1360   // than that of [NativeWidget B]. This is why we need to call
   1361   // GetTopLevelWidget() here.
   1362   return GetWidget()->GetTopLevelWidget()->GetNativeWindow();
   1363 }
   1364 
   1365 ui::TextInputType Textfield::GetTextInputType() const {
   1366   if (read_only() || !enabled())
   1367     return ui::TEXT_INPUT_TYPE_NONE;
   1368   return text_input_type_;
   1369 }
   1370 
   1371 ui::TextInputMode Textfield::GetTextInputMode() const {
   1372   return ui::TEXT_INPUT_MODE_DEFAULT;
   1373 }
   1374 
   1375 bool Textfield::CanComposeInline() const {
   1376   return true;
   1377 }
   1378 
   1379 gfx::Rect Textfield::GetCaretBounds() const {
   1380   gfx::Rect rect = GetRenderText()->GetUpdatedCursorBounds();
   1381   ConvertRectToScreen(this, &rect);
   1382   return rect;
   1383 }
   1384 
   1385 bool Textfield::GetCompositionCharacterBounds(uint32 index,
   1386                                               gfx::Rect* rect) const {
   1387   DCHECK(rect);
   1388   if (!HasCompositionText())
   1389     return false;
   1390   gfx::RenderText* render_text = GetRenderText();
   1391   const gfx::Range& composition_range = render_text->GetCompositionRange();
   1392   DCHECK(!composition_range.is_empty());
   1393 
   1394   size_t text_index = composition_range.start() + index;
   1395   if (composition_range.end() <= text_index)
   1396     return false;
   1397   if (!render_text->IsValidCursorIndex(text_index)) {
   1398     text_index = render_text->IndexOfAdjacentGrapheme(
   1399         text_index, gfx::CURSOR_BACKWARD);
   1400   }
   1401   if (text_index < composition_range.start())
   1402     return false;
   1403   const gfx::SelectionModel caret(text_index, gfx::CURSOR_BACKWARD);
   1404   *rect = render_text->GetCursorBounds(caret, false);
   1405   ConvertRectToScreen(this, rect);
   1406   return true;
   1407 }
   1408 
   1409 bool Textfield::HasCompositionText() const {
   1410   return model_->HasCompositionText();
   1411 }
   1412 
   1413 bool Textfield::GetTextRange(gfx::Range* range) const {
   1414   if (!ImeEditingAllowed())
   1415     return false;
   1416 
   1417   model_->GetTextRange(range);
   1418   return true;
   1419 }
   1420 
   1421 bool Textfield::GetCompositionTextRange(gfx::Range* range) const {
   1422   if (!ImeEditingAllowed())
   1423     return false;
   1424 
   1425   model_->GetCompositionTextRange(range);
   1426   return true;
   1427 }
   1428 
   1429 bool Textfield::GetSelectionRange(gfx::Range* range) const {
   1430   if (!ImeEditingAllowed())
   1431     return false;
   1432   *range = GetRenderText()->selection();
   1433   return true;
   1434 }
   1435 
   1436 bool Textfield::SetSelectionRange(const gfx::Range& range) {
   1437   if (!ImeEditingAllowed() || !range.IsValid())
   1438     return false;
   1439   OnBeforeUserAction();
   1440   SelectRange(range);
   1441   OnAfterUserAction();
   1442   return true;
   1443 }
   1444 
   1445 bool Textfield::DeleteRange(const gfx::Range& range) {
   1446   if (!ImeEditingAllowed() || range.is_empty())
   1447     return false;
   1448 
   1449   OnBeforeUserAction();
   1450   model_->SelectRange(range);
   1451   if (model_->HasSelection()) {
   1452     model_->DeleteSelection();
   1453     UpdateAfterChange(true, true);
   1454   }
   1455   OnAfterUserAction();
   1456   return true;
   1457 }
   1458 
   1459 bool Textfield::GetTextFromRange(const gfx::Range& range,
   1460                                  base::string16* range_text) const {
   1461   if (!ImeEditingAllowed() || !range.IsValid())
   1462     return false;
   1463 
   1464   gfx::Range text_range;
   1465   if (!GetTextRange(&text_range) || !text_range.Contains(range))
   1466     return false;
   1467 
   1468   *range_text = model_->GetTextFromRange(range);
   1469   return true;
   1470 }
   1471 
   1472 void Textfield::OnInputMethodChanged() {}
   1473 
   1474 bool Textfield::ChangeTextDirectionAndLayoutAlignment(
   1475     base::i18n::TextDirection direction) {
   1476   // Restore text directionality mode when the indicated direction matches the
   1477   // current forced mode; otherwise, force the mode indicated. This helps users
   1478   // manage BiDi text layout without getting stuck in forced LTR or RTL modes.
   1479   const gfx::DirectionalityMode mode = direction == base::i18n::RIGHT_TO_LEFT ?
   1480       gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR;
   1481   if (mode == GetRenderText()->directionality_mode())
   1482     GetRenderText()->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT);
   1483   else
   1484     GetRenderText()->SetDirectionalityMode(mode);
   1485   SchedulePaint();
   1486   return true;
   1487 }
   1488 
   1489 void Textfield::ExtendSelectionAndDelete(size_t before, size_t after) {
   1490   gfx::Range range = GetRenderText()->selection();
   1491   DCHECK_GE(range.start(), before);
   1492 
   1493   range.set_start(range.start() - before);
   1494   range.set_end(range.end() + after);
   1495   gfx::Range text_range;
   1496   if (GetTextRange(&text_range) && text_range.Contains(range))
   1497     DeleteRange(range);
   1498 }
   1499 
   1500 void Textfield::EnsureCaretInRect(const gfx::Rect& rect) {}
   1501 
   1502 void Textfield::OnCandidateWindowShown() {}
   1503 
   1504 void Textfield::OnCandidateWindowUpdated() {}
   1505 
   1506 void Textfield::OnCandidateWindowHidden() {}
   1507 
   1508 bool Textfield::IsEditingCommandEnabled(int command_id) {
   1509   return IsCommandIdEnabled(command_id);
   1510 }
   1511 
   1512 void Textfield::ExecuteEditingCommand(int command_id) {
   1513   ExecuteCommand(command_id);
   1514 }
   1515 
   1516 ////////////////////////////////////////////////////////////////////////////////
   1517 // Textfield, protected:
   1518 
   1519 gfx::RenderText* Textfield::GetRenderText() const {
   1520   return model_->render_text();
   1521 }
   1522 
   1523 base::string16 Textfield::GetSelectionClipboardText() const {
   1524   base::string16 selection_clipboard_text;
   1525   ui::Clipboard::GetForCurrentThread()->ReadText(
   1526       ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text);
   1527   return selection_clipboard_text;
   1528 }
   1529 
   1530 ////////////////////////////////////////////////////////////////////////////////
   1531 // Textfield, private:
   1532 
   1533 void Textfield::AccessibilitySetValue(const base::string16& new_value) {
   1534   if (!read_only()) {
   1535     SetText(new_value);
   1536     ClearSelection();
   1537   }
   1538 }
   1539 
   1540 void Textfield::UpdateBackgroundColor() {
   1541   const SkColor color = GetBackgroundColor();
   1542   set_background(Background::CreateSolidBackground(color));
   1543   GetRenderText()->set_background_is_transparent(SkColorGetA(color) != 0xFF);
   1544   SchedulePaint();
   1545 }
   1546 
   1547 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) {
   1548   if (text_changed) {
   1549     if (controller_)
   1550       controller_->ContentsChanged(this, text());
   1551     NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
   1552   }
   1553   if (cursor_changed) {
   1554     cursor_visible_ = true;
   1555     RepaintCursor();
   1556     if (cursor_repaint_timer_.IsRunning())
   1557       cursor_repaint_timer_.Reset();
   1558     if (!text_changed) {
   1559       // TEXT_CHANGED implies SELECTION_CHANGED, so we only need to fire
   1560       // this if only the selection changed.
   1561       NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION_CHANGED, true);
   1562     }
   1563   }
   1564   if (text_changed || cursor_changed) {
   1565     OnCaretBoundsChanged();
   1566     SchedulePaint();
   1567   }
   1568 }
   1569 
   1570 void Textfield::UpdateCursor() {
   1571   const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
   1572   cursor_visible_ = !cursor_visible_ || (caret_blink_ms == 0);
   1573   RepaintCursor();
   1574 }
   1575 
   1576 void Textfield::RepaintCursor() {
   1577   gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds());
   1578   r.Inset(-1, -1, -1, -1);
   1579   SchedulePaintInRect(r);
   1580 }
   1581 
   1582 void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) {
   1583   TRACE_EVENT0("views", "Textfield::PaintTextAndCursor");
   1584   canvas->Save();
   1585 
   1586   // Draw placeholder text if needed.
   1587   gfx::RenderText* render_text = GetRenderText();
   1588   if (text().empty() && !GetPlaceholderText().empty()) {
   1589     canvas->DrawStringRect(GetPlaceholderText(), GetFontList(),
   1590         placeholder_text_color(), render_text->display_rect());
   1591   }
   1592 
   1593   // Draw the text, cursor, and selection.
   1594   render_text->set_cursor_visible(cursor_visible_ && !drop_cursor_visible_ &&
   1595                                   !HasSelection());
   1596   render_text->Draw(canvas);
   1597 
   1598   // Draw the detached drop cursor that marks where the text will be dropped.
   1599   if (drop_cursor_visible_)
   1600     render_text->DrawCursor(canvas, drop_cursor_position_);
   1601 
   1602   canvas->Restore();
   1603 }
   1604 
   1605 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
   1606   if (model_->MoveCursorTo(point, select))
   1607     UpdateAfterChange(false, true);
   1608 }
   1609 
   1610 void Textfield::SelectThroughLastDragLocation() {
   1611   OnBeforeUserAction();
   1612   model_->MoveCursorTo(last_drag_location_, true);
   1613   if (aggregated_clicks_ == 1) {
   1614     model_->SelectWord();
   1615     // Expand the selection so the initially selected word remains selected.
   1616     gfx::Range selection = GetRenderText()->selection();
   1617     const size_t min = std::min(selection.GetMin(),
   1618                                 double_click_word_.GetMin());
   1619     const size_t max = std::max(selection.GetMax(),
   1620                                 double_click_word_.GetMax());
   1621     const bool reversed = selection.is_reversed();
   1622     selection.set_start(reversed ? max : min);
   1623     selection.set_end(reversed ? min : max);
   1624     model_->SelectRange(selection);
   1625   }
   1626   UpdateAfterChange(false, true);
   1627   OnAfterUserAction();
   1628 }
   1629 
   1630 void Textfield::OnCaretBoundsChanged() {
   1631   if (GetInputMethod())
   1632     GetInputMethod()->OnCaretBoundsChanged(this);
   1633   if (touch_selection_controller_)
   1634     touch_selection_controller_->SelectionChanged();
   1635 }
   1636 
   1637 void Textfield::OnBeforeUserAction() {
   1638   DCHECK(!performing_user_action_);
   1639   performing_user_action_ = true;
   1640   if (controller_)
   1641     controller_->OnBeforeUserAction(this);
   1642 }
   1643 
   1644 void Textfield::OnAfterUserAction() {
   1645   if (controller_)
   1646     controller_->OnAfterUserAction(this);
   1647   DCHECK(performing_user_action_);
   1648   performing_user_action_ = false;
   1649 }
   1650 
   1651 bool Textfield::Cut() {
   1652   if (!read_only() && text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD &&
   1653       model_->Cut()) {
   1654     if (controller_)
   1655       controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_COPY_PASTE);
   1656     return true;
   1657   }
   1658   return false;
   1659 }
   1660 
   1661 bool Textfield::Copy() {
   1662   if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD && model_->Copy()) {
   1663     if (controller_)
   1664       controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_COPY_PASTE);
   1665     return true;
   1666   }
   1667   return false;
   1668 }
   1669 
   1670 bool Textfield::Paste() {
   1671   if (!read_only() && model_->Paste()) {
   1672     if (controller_)
   1673       controller_->OnAfterPaste();
   1674     return true;
   1675   }
   1676   return false;
   1677 }
   1678 
   1679 void Textfield::UpdateContextMenu() {
   1680   if (!context_menu_contents_.get()) {
   1681     context_menu_contents_.reset(new ui::SimpleMenuModel(this));
   1682     context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO);
   1683     context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
   1684     context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
   1685     context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
   1686     context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
   1687     context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE);
   1688     context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
   1689     context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
   1690                                                 IDS_APP_SELECT_ALL);
   1691     if (controller_)
   1692       controller_->UpdateContextMenu(context_menu_contents_.get());
   1693   }
   1694   context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get()));
   1695 }
   1696 
   1697 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) {
   1698   if (event.IsOnlyLeftMouseButton()) {
   1699     base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
   1700     if (time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
   1701         !ExceededDragThreshold(event.location() - last_click_location_)) {
   1702       // Upon clicking after a triple click, the count should go back to double
   1703       // click and alternate between double and triple. This assignment maps
   1704       // 0 to 1, 1 to 2, 2 to 1.
   1705       aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
   1706     } else {
   1707       aggregated_clicks_ = 0;
   1708     }
   1709     last_click_time_ = event.time_stamp();
   1710     last_click_location_ = event.location();
   1711   }
   1712 }
   1713 
   1714 bool Textfield::ImeEditingAllowed() const {
   1715   // Disallow input method editing of password fields.
   1716   ui::TextInputType t = GetTextInputType();
   1717   return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD);
   1718 }
   1719 
   1720 void Textfield::RevealPasswordChar(int index) {
   1721   GetRenderText()->SetObscuredRevealIndex(index);
   1722   SchedulePaint();
   1723 
   1724   if (index != -1) {
   1725     password_reveal_timer_.Start(FROM_HERE, password_reveal_duration_,
   1726         base::Bind(&Textfield::RevealPasswordChar,
   1727                    weak_ptr_factory_.GetWeakPtr(), -1));
   1728   }
   1729 }
   1730 
   1731 void Textfield::CreateTouchSelectionControllerAndNotifyIt() {
   1732   if (!touch_selection_controller_) {
   1733     touch_selection_controller_.reset(
   1734         ui::TouchSelectionController::create(this));
   1735   }
   1736   if (touch_selection_controller_)
   1737     touch_selection_controller_->SelectionChanged();
   1738 }
   1739 
   1740 void Textfield::UpdateSelectionClipboard() const {
   1741 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
   1742   if (performing_user_action_ && HasSelection()) {
   1743     ui::ScopedClipboardWriter(
   1744         ui::Clipboard::GetForCurrentThread(),
   1745         ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText());
   1746     if (controller_)
   1747       controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
   1748   }
   1749 #endif
   1750 }
   1751 
   1752 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) {
   1753   DCHECK(event.IsOnlyMiddleMouseButton());
   1754   DCHECK(!read_only());
   1755   base::string16 selection_clipboard_text = GetSelectionClipboardText();
   1756   if (!selection_clipboard_text.empty()) {
   1757     OnBeforeUserAction();
   1758     gfx::Range range = GetSelectionModel().selection();
   1759     gfx::LogicalCursorDirection affinity = GetSelectionModel().caret_affinity();
   1760     const gfx::SelectionModel mouse =
   1761         GetRenderText()->FindCursorPosition(event.location());
   1762     model_->MoveCursorTo(mouse);
   1763     model_->InsertText(selection_clipboard_text);
   1764     // Update the new selection range as needed.
   1765     if (range.GetMin() >= mouse.caret_pos()) {
   1766       const size_t length = selection_clipboard_text.length();
   1767       range = gfx::Range(range.start() + length, range.end() + length);
   1768     }
   1769     model_->MoveCursorTo(gfx::SelectionModel(range, affinity));
   1770     UpdateAfterChange(true, true);
   1771     OnAfterUserAction();
   1772   }
   1773 }
   1774 
   1775 }  // namespace views
   1776