Home | History | Annotate | Download | only in textfield
      1 // Copyright (c) 2013 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/native_textfield_views.h"
      6 
      7 #include <algorithm>
      8 #include <set>
      9 
     10 #include "base/bind.h"
     11 #include "base/debug/trace_event.h"
     12 #include "base/i18n/case_conversion.h"
     13 #include "base/logging.h"
     14 #include "base/message_loop/message_loop.h"
     15 #include "base/strings/utf_string_conversions.h"
     16 #include "grit/ui_strings.h"
     17 #include "third_party/icu/source/common/unicode/uchar.h"
     18 #include "third_party/skia/include/core/SkColor.h"
     19 #include "ui/base/clipboard/clipboard.h"
     20 #include "ui/base/dragdrop/drag_drop_types.h"
     21 #include "ui/base/dragdrop/drag_utils.h"
     22 #include "ui/base/events/event.h"
     23 #include "ui/base/l10n/l10n_util.h"
     24 #include "ui/base/range/range.h"
     25 #include "ui/base/ui_base_switches_util.h"
     26 #include "ui/compositor/layer.h"
     27 #include "ui/gfx/canvas.h"
     28 #include "ui/gfx/insets.h"
     29 #include "ui/gfx/render_text.h"
     30 #include "ui/gfx/text_constants.h"
     31 #include "ui/native_theme/native_theme.h"
     32 #include "ui/views/background.h"
     33 #include "ui/views/border.h"
     34 #include "ui/views/controls/focusable_border.h"
     35 #include "ui/views/controls/menu/menu_item_view.h"
     36 #include "ui/views/controls/menu/menu_model_adapter.h"
     37 #include "ui/views/controls/menu/menu_runner.h"
     38 #include "ui/views/controls/textfield/textfield.h"
     39 #include "ui/views/controls/textfield/textfield_controller.h"
     40 #include "ui/views/controls/textfield/textfield_views_model.h"
     41 #include "ui/views/drag_utils.h"
     42 #include "ui/views/ime/input_method.h"
     43 #include "ui/views/metrics.h"
     44 #include "ui/views/widget/widget.h"
     45 
     46 #if defined(USE_AURA)
     47 #include "ui/base/cursor/cursor.h"
     48 #endif
     49 
     50 #if defined(OS_WIN) && defined(USE_AURA)
     51 #include "base/win/win_util.h"
     52 #endif
     53 
     54 namespace {
     55 
     56 void ConvertRectToScreen(const views::View* src, gfx::Rect* r) {
     57   DCHECK(src);
     58 
     59   gfx::Point new_origin = r->origin();
     60   views::View::ConvertPointToScreen(src, &new_origin);
     61   r->set_origin(new_origin);
     62 }
     63 
     64 }  // namespace
     65 
     66 namespace views {
     67 
     68 const char NativeTextfieldViews::kViewClassName[] =
     69     "views/NativeTextfieldViews";
     70 
     71 const int NativeTextfieldViews::kCursorBlinkCycleMs = 1000;
     72 
     73 NativeTextfieldViews::NativeTextfieldViews(Textfield* parent)
     74     : textfield_(parent),
     75       model_(new TextfieldViewsModel(this)),
     76       text_border_(new FocusableBorder()),
     77       is_cursor_visible_(false),
     78       is_drop_cursor_visible_(false),
     79       skip_input_method_cancel_composition_(false),
     80       initiating_drag_(false),
     81       cursor_timer_(this),
     82       aggregated_clicks_(0) {
     83   set_border(text_border_);
     84   GetRenderText()->SetFontList(textfield_->font_list());
     85   UpdateColorsFromTheme(GetNativeTheme());
     86   set_context_menu_controller(this);
     87   parent->set_context_menu_controller(this);
     88   set_drag_controller(this);
     89 }
     90 
     91 NativeTextfieldViews::~NativeTextfieldViews() {
     92 }
     93 
     94 ////////////////////////////////////////////////////////////////////////////////
     95 // NativeTextfieldViews, View overrides:
     96 
     97 bool NativeTextfieldViews::OnMousePressed(const ui::MouseEvent& event) {
     98   OnBeforeUserAction();
     99   TrackMouseClicks(event);
    100 
    101   TextfieldController* controller = textfield_->GetController();
    102   if (!(controller && controller->HandleMouseEvent(textfield_, event)) &&
    103       !textfield_->OnMousePressed(event)) {
    104     HandleMousePressEvent(event);
    105   }
    106 
    107   OnAfterUserAction();
    108   touch_selection_controller_.reset();
    109   return true;
    110 }
    111 
    112 bool NativeTextfieldViews::ExceededDragThresholdFromLastClickLocation(
    113     const ui::MouseEvent& event) {
    114   return ExceededDragThreshold(event.location() - last_click_location_);
    115 }
    116 
    117 bool NativeTextfieldViews::OnMouseDragged(const ui::MouseEvent& event) {
    118   // Don't adjust the cursor on a potential drag and drop, or if the mouse
    119   // movement from the last mouse click does not exceed the drag threshold.
    120   if (initiating_drag_ || !ExceededDragThresholdFromLastClickLocation(event) ||
    121       !event.IsOnlyLeftMouseButton()) {
    122     return true;
    123   }
    124 
    125   OnBeforeUserAction();
    126   // TODO: Remove once NativeTextfield implementations are consolidated to
    127   // Textfield.
    128   if (!textfield_->OnMouseDragged(event)) {
    129     MoveCursorTo(event.location(), true);
    130     if (aggregated_clicks_ == 1) {
    131       model_->SelectWord();
    132       // Expand the selection so the initially selected word remains selected.
    133       ui::Range selection = GetRenderText()->selection();
    134       const size_t min = std::min(selection.GetMin(),
    135                                   double_click_word_.GetMin());
    136       const size_t max = std::max(selection.GetMax(),
    137                                   double_click_word_.GetMax());
    138       const bool reversed = selection.is_reversed();
    139       selection.set_start(reversed ? max : min);
    140       selection.set_end(reversed ? min : max);
    141       model_->SelectRange(selection);
    142     }
    143     SchedulePaint();
    144   }
    145   OnAfterUserAction();
    146   return true;
    147 }
    148 
    149 void NativeTextfieldViews::OnMouseReleased(const ui::MouseEvent& event) {
    150   OnBeforeUserAction();
    151   // TODO: Remove once NativeTextfield implementations are consolidated to
    152   // Textfield.
    153   textfield_->OnMouseReleased(event);
    154   // Cancel suspected drag initiations, the user was clicking in the selection.
    155   if (initiating_drag_ && MoveCursorTo(event.location(), false))
    156     SchedulePaint();
    157   initiating_drag_ = false;
    158   OnAfterUserAction();
    159 }
    160 
    161 void NativeTextfieldViews::OnGestureEvent(ui::GestureEvent* event) {
    162   textfield_->OnGestureEvent(event);
    163   if (event->handled())
    164     return;
    165 
    166   switch (event->type()) {
    167     case ui::ET_GESTURE_TAP_DOWN:
    168       OnBeforeUserAction();
    169       textfield_->RequestFocus();
    170       // We don't deselect if the point is in the selection
    171       // because TAP_DOWN may turn into a LONG_PRESS.
    172       if (!GetRenderText()->IsPointInSelection(event->location()) &&
    173           MoveCursorTo(event->location(), false))
    174         SchedulePaint();
    175       OnAfterUserAction();
    176       event->SetHandled();
    177       break;
    178     case ui::ET_GESTURE_SCROLL_UPDATE:
    179       OnBeforeUserAction();
    180       if (MoveCursorTo(event->location(), true))
    181         SchedulePaint();
    182       OnAfterUserAction();
    183       event->SetHandled();
    184       break;
    185     case ui::ET_GESTURE_TAP:
    186       if (event->details().tap_count() == 1) {
    187         CreateTouchSelectionControllerAndNotifyIt();
    188       } else {
    189         OnBeforeUserAction();
    190         SelectAll(false);
    191         OnAfterUserAction();
    192         event->SetHandled();
    193       }
    194       break;
    195     case ui::ET_GESTURE_LONG_PRESS:
    196       // If long press happens outside selection, select word and show context
    197       // menu (If touch selection is enabled, context menu is shown by the
    198       // |touch_selection_controller_|, hence we mark the event handled.
    199       // Otherwise, the regular context menu will be shown by views).
    200       // If long press happens in selected text and touch drag drop is enabled,
    201       // we will turn off touch selection (if one exists) and let views do drag
    202       // drop.
    203       if (!GetRenderText()->IsPointInSelection(event->location())) {
    204         OnBeforeUserAction();
    205         model_->SelectWord();
    206         touch_selection_controller_.reset(
    207             ui::TouchSelectionController::create(this));
    208         OnCaretBoundsChanged();
    209         SchedulePaint();
    210         OnAfterUserAction();
    211         if (touch_selection_controller_.get())
    212           event->SetHandled();
    213       } else if (switches::IsTouchDragDropEnabled()) {
    214         initiating_drag_ = true;
    215         touch_selection_controller_.reset();
    216       } else {
    217         if (!touch_selection_controller_.get())
    218           CreateTouchSelectionControllerAndNotifyIt();
    219         if (touch_selection_controller_.get())
    220           event->SetHandled();
    221       }
    222       return;
    223     case ui::ET_GESTURE_LONG_TAP:
    224       if (!touch_selection_controller_.get())
    225         CreateTouchSelectionControllerAndNotifyIt();
    226 
    227       // If touch selection is enabled, the context menu on long tap will be
    228       // shown by the |touch_selection_controller_|, hence we mark the event
    229       // handled so views does not try to show context menu on it.
    230       if (touch_selection_controller_.get())
    231         event->SetHandled();
    232       break;
    233     default:
    234       View::OnGestureEvent(event);
    235       return;
    236   }
    237   PlatformGestureEventHandling(event);
    238 }
    239 
    240 bool NativeTextfieldViews::OnKeyPressed(const ui::KeyEvent& event) {
    241   // OnKeyPressed/OnKeyReleased/OnFocus/OnBlur will never be invoked on
    242   // NativeTextfieldViews as it will never gain focus.
    243   NOTREACHED();
    244   return false;
    245 }
    246 
    247 bool NativeTextfieldViews::OnKeyReleased(const ui::KeyEvent& event) {
    248   NOTREACHED();
    249   return false;
    250 }
    251 
    252 bool NativeTextfieldViews::GetDropFormats(
    253     int* formats,
    254     std::set<OSExchangeData::CustomFormat>* custom_formats) {
    255   if (!textfield_->enabled() || textfield_->read_only())
    256     return false;
    257   // TODO(msw): Can we support URL, FILENAME, etc.?
    258   *formats = ui::OSExchangeData::STRING;
    259   TextfieldController* controller = textfield_->GetController();
    260   if (controller)
    261     controller->AppendDropFormats(formats, custom_formats);
    262   return true;
    263 }
    264 
    265 bool NativeTextfieldViews::CanDrop(const OSExchangeData& data) {
    266   int formats;
    267   std::set<OSExchangeData::CustomFormat> custom_formats;
    268   GetDropFormats(&formats, &custom_formats);
    269   return textfield_->enabled() && !textfield_->read_only() &&
    270       data.HasAnyFormat(formats, custom_formats);
    271 }
    272 
    273 int NativeTextfieldViews::OnDragUpdated(const ui::DropTargetEvent& event) {
    274   DCHECK(CanDrop(event.data()));
    275 
    276   const ui::Range& selection = GetRenderText()->selection();
    277   drop_cursor_position_ = GetRenderText()->FindCursorPosition(event.location());
    278   bool in_selection = !selection.is_empty() &&
    279       selection.Contains(ui::Range(drop_cursor_position_.caret_pos()));
    280   is_drop_cursor_visible_ = !in_selection;
    281   // TODO(msw): Pan over text when the user drags to the visible text edge.
    282   OnCaretBoundsChanged();
    283   SchedulePaint();
    284 
    285   if (initiating_drag_) {
    286     if (in_selection)
    287       return ui::DragDropTypes::DRAG_NONE;
    288     return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY :
    289                                    ui::DragDropTypes::DRAG_MOVE;
    290   }
    291   return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
    292 }
    293 
    294 void NativeTextfieldViews::OnDragExited() {
    295   is_drop_cursor_visible_ = false;
    296   SchedulePaint();
    297 }
    298 
    299 int NativeTextfieldViews::OnPerformDrop(const ui::DropTargetEvent& event) {
    300   DCHECK(CanDrop(event.data()));
    301 
    302   is_drop_cursor_visible_ = false;
    303 
    304   TextfieldController* controller = textfield_->GetController();
    305   if (controller) {
    306       int drag_operation = controller->OnDrop(event.data());
    307       if (drag_operation != ui::DragDropTypes::DRAG_NONE)
    308         return drag_operation;
    309   }
    310 
    311   DCHECK(!initiating_drag_ ||
    312          !GetRenderText()->IsPointInSelection(event.location()));
    313   OnBeforeUserAction();
    314   skip_input_method_cancel_composition_ = true;
    315 
    316   gfx::SelectionModel drop_destination_model =
    317       GetRenderText()->FindCursorPosition(event.location());
    318   string16 text;
    319   event.data().GetString(&text);
    320   text = GetTextForDisplay(text);
    321 
    322   // Delete the current selection for a drag and drop within this view.
    323   const bool move = initiating_drag_ && !event.IsControlDown() &&
    324                     event.source_operations() & ui::DragDropTypes::DRAG_MOVE;
    325   if (move) {
    326     // Adjust the drop destination if it is on or after the current selection.
    327     size_t drop = drop_destination_model.caret_pos();
    328     drop -= GetSelectedRange().Intersect(ui::Range(0, drop)).length();
    329     model_->DeleteSelectionAndInsertTextAt(text, drop);
    330   } else {
    331     model_->MoveCursorTo(drop_destination_model);
    332     // Drop always inserts text even if the textfield is not in insert mode.
    333     model_->InsertText(text);
    334   }
    335   skip_input_method_cancel_composition_ = false;
    336   UpdateAfterChange(true, true);
    337   OnAfterUserAction();
    338   return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY;
    339 }
    340 
    341 void NativeTextfieldViews::OnDragDone() {
    342   initiating_drag_ = false;
    343   is_drop_cursor_visible_ = false;
    344 }
    345 
    346 void NativeTextfieldViews::OnPaint(gfx::Canvas* canvas) {
    347   text_border_->set_has_focus(textfield_->HasFocus());
    348   OnPaintBackground(canvas);
    349   PaintTextAndCursor(canvas);
    350   if (textfield_->draw_border())
    351     OnPaintBorder(canvas);
    352 }
    353 
    354 void NativeTextfieldViews::OnFocus() {
    355   NOTREACHED();
    356 }
    357 
    358 void NativeTextfieldViews::OnBlur() {
    359   NOTREACHED();
    360 }
    361 
    362 void NativeTextfieldViews::OnNativeThemeChanged(const ui::NativeTheme* theme) {
    363   UpdateColorsFromTheme(theme);
    364 }
    365 
    366 void NativeTextfieldViews::SelectRect(const gfx::Point& start,
    367                                       const gfx::Point& end) {
    368   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
    369     return;
    370 
    371   gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start);
    372   gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end);
    373   gfx::SelectionModel selection(
    374       ui::Range(start_caret.caret_pos(), end_caret.caret_pos()),
    375       end_caret.caret_affinity());
    376 
    377   OnBeforeUserAction();
    378   model_->SelectSelectionModel(selection);
    379   OnCaretBoundsChanged();
    380   SchedulePaint();
    381   OnAfterUserAction();
    382 }
    383 
    384 void NativeTextfieldViews::MoveCaretTo(const gfx::Point& point) {
    385   SelectRect(point, point);
    386 }
    387 
    388 void NativeTextfieldViews::GetSelectionEndPoints(gfx::Rect* p1,
    389                                                  gfx::Rect* p2) {
    390   gfx::RenderText* render_text = GetRenderText();
    391   const gfx::SelectionModel& sel = render_text->selection_model();
    392   gfx::SelectionModel start_sel =
    393       render_text->GetSelectionModelForSelectionStart();
    394   *p1 = render_text->GetCursorBounds(start_sel, true);
    395   *p2 = render_text->GetCursorBounds(sel, true);
    396 }
    397 
    398 gfx::Rect NativeTextfieldViews::GetBounds() {
    399   return bounds();
    400 }
    401 
    402 gfx::NativeView NativeTextfieldViews::GetNativeView() {
    403   return GetWidget()->GetNativeView();
    404 }
    405 
    406 void NativeTextfieldViews::ConvertPointToScreen(gfx::Point* point) {
    407   View::ConvertPointToScreen(this, point);
    408 }
    409 
    410 void NativeTextfieldViews::ConvertPointFromScreen(gfx::Point* point) {
    411   View::ConvertPointFromScreen(this, point);
    412 }
    413 
    414 bool NativeTextfieldViews::DrawsHandles() {
    415   return false;
    416 }
    417 
    418 void NativeTextfieldViews::OpenContextMenu(const gfx::Point& anchor) {
    419   touch_selection_controller_.reset();
    420   ShowContextMenu(anchor, ui::MENU_SOURCE_TOUCH_EDIT_MENU);
    421 }
    422 
    423 gfx::NativeCursor NativeTextfieldViews::GetCursor(const ui::MouseEvent& event) {
    424   bool in_selection = GetRenderText()->IsPointInSelection(event.location());
    425   bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
    426   bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
    427 #if defined(USE_AURA)
    428   return text_cursor ? ui::kCursorIBeam : ui::kCursorNull;
    429 #elif defined(OS_WIN)
    430   static HCURSOR ibeam = LoadCursor(NULL, IDC_IBEAM);
    431   static HCURSOR arrow = LoadCursor(NULL, IDC_ARROW);
    432   return text_cursor ? ibeam : arrow;
    433 #endif
    434 }
    435 
    436 /////////////////////////////////////////////////////////////////
    437 // NativeTextfieldViews, ContextMenuController overrides:
    438 void NativeTextfieldViews::ShowContextMenuForView(
    439     View* source,
    440     const gfx::Point& point,
    441     ui::MenuSourceType source_type) {
    442   UpdateContextMenu();
    443   if (context_menu_runner_->RunMenuAt(GetWidget(), NULL,
    444           gfx::Rect(point, gfx::Size()), views::MenuItemView::TOPLEFT,
    445           source_type,
    446           MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
    447       MenuRunner::MENU_DELETED)
    448     return;
    449 }
    450 
    451 /////////////////////////////////////////////////////////////////
    452 // NativeTextfieldViews, views::DragController overrides:
    453 void NativeTextfieldViews::WriteDragDataForView(views::View* sender,
    454                                                 const gfx::Point& press_pt,
    455                                                 OSExchangeData* data) {
    456   DCHECK_NE(ui::DragDropTypes::DRAG_NONE,
    457             GetDragOperationsForView(sender, press_pt));
    458   data->SetString(GetSelectedText());
    459   scoped_ptr<gfx::Canvas> canvas(
    460       views::GetCanvasForDragImage(textfield_->GetWidget(), size()));
    461   GetRenderText()->DrawSelectedTextForDrag(canvas.get());
    462   drag_utils::SetDragImageOnDataObject(*canvas, size(),
    463                                        press_pt.OffsetFromOrigin(),
    464                                        data);
    465   TextfieldController* controller = textfield_->GetController();
    466   if (controller)
    467     controller->OnWriteDragData(data);
    468 }
    469 
    470 int NativeTextfieldViews::GetDragOperationsForView(views::View* sender,
    471                                                    const gfx::Point& p) {
    472   int drag_operations = ui::DragDropTypes::DRAG_COPY;
    473   if (!textfield_->enabled() || textfield_->IsObscured() ||
    474       !GetRenderText()->IsPointInSelection(p))
    475     drag_operations = ui::DragDropTypes::DRAG_NONE;
    476   else if (sender == this && !textfield_->read_only())
    477     drag_operations =
    478         ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY;
    479   TextfieldController* controller = textfield_->GetController();
    480   if (controller)
    481     controller->OnGetDragOperationsForTextfield(&drag_operations);
    482   return drag_operations;
    483 }
    484 
    485 bool NativeTextfieldViews::CanStartDragForView(View* sender,
    486                                                const gfx::Point& press_pt,
    487                                                const gfx::Point& p) {
    488   return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt);
    489 }
    490 
    491 /////////////////////////////////////////////////////////////////
    492 // NativeTextfieldViews, NativeTextifieldWrapper overrides:
    493 
    494 string16 NativeTextfieldViews::GetText() const {
    495   return model_->GetText();
    496 }
    497 
    498 void NativeTextfieldViews::UpdateText() {
    499   model_->SetText(GetTextForDisplay(textfield_->text()));
    500   OnCaretBoundsChanged();
    501   SchedulePaint();
    502   textfield_->NotifyAccessibilityEvent(
    503       ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
    504 }
    505 
    506 void NativeTextfieldViews::AppendText(const string16& text) {
    507   if (text.empty())
    508     return;
    509   model_->Append(GetTextForDisplay(text));
    510   OnCaretBoundsChanged();
    511   SchedulePaint();
    512 }
    513 
    514 void NativeTextfieldViews::InsertOrReplaceText(const string16& text) {
    515   if (text.empty())
    516     return;
    517   model_->InsertText(text);
    518   OnCaretBoundsChanged();
    519   SchedulePaint();
    520 }
    521 
    522 base::i18n::TextDirection NativeTextfieldViews::GetTextDirection() const {
    523   return GetRenderText()->GetTextDirection();
    524 }
    525 
    526 string16 NativeTextfieldViews::GetSelectedText() const {
    527   return model_->GetSelectedText();
    528 }
    529 
    530 void NativeTextfieldViews::SelectAll(bool reversed) {
    531   model_->SelectAll(reversed);
    532   OnCaretBoundsChanged();
    533   SchedulePaint();
    534 }
    535 
    536 void NativeTextfieldViews::ClearSelection() {
    537   model_->ClearSelection();
    538   OnCaretBoundsChanged();
    539   SchedulePaint();
    540 }
    541 
    542 void NativeTextfieldViews::UpdateBorder() {
    543   // By default, if a caller calls Textfield::RemoveBorder() and does not set
    544   // any explicit margins, they should get zero margins.  But also call
    545   // UpdateXXXMargins() so we respect any explicitly-set margins.
    546   //
    547   // NOTE: If someday Textfield supports toggling |draw_border_| back on, we'll
    548   // need to update this conditional to set the insets to their default values.
    549   if (!textfield_->draw_border())
    550     text_border_->SetInsets(0, 0, 0, 0);
    551   UpdateHorizontalMargins();
    552   UpdateVerticalMargins();
    553 }
    554 
    555 void NativeTextfieldViews::UpdateTextColor() {
    556   SetColor(textfield_->GetTextColor());
    557 }
    558 
    559 void NativeTextfieldViews::UpdateBackgroundColor() {
    560   const SkColor color = textfield_->GetBackgroundColor();
    561   set_background(Background::CreateSolidBackground(color));
    562   GetRenderText()->set_background_is_transparent(SkColorGetA(color) != 0xFF);
    563   SchedulePaint();
    564 }
    565 
    566 void NativeTextfieldViews::UpdateReadOnly() {
    567   OnTextInputTypeChanged();
    568 }
    569 
    570 void NativeTextfieldViews::UpdateFont() {
    571   GetRenderText()->SetFontList(textfield_->font_list());
    572   OnCaretBoundsChanged();
    573 }
    574 
    575 void NativeTextfieldViews::UpdateIsObscured() {
    576   GetRenderText()->SetObscured(textfield_->IsObscured());
    577   OnCaretBoundsChanged();
    578   SchedulePaint();
    579   OnTextInputTypeChanged();
    580 }
    581 
    582 void NativeTextfieldViews::UpdateEnabled() {
    583   SetEnabled(textfield_->enabled());
    584   SchedulePaint();
    585   OnTextInputTypeChanged();
    586 }
    587 
    588 gfx::Insets NativeTextfieldViews::CalculateInsets() {
    589   return GetInsets();
    590 }
    591 
    592 void NativeTextfieldViews::UpdateHorizontalMargins() {
    593   int left, right;
    594   if (!textfield_->GetHorizontalMargins(&left, &right))
    595     return;
    596   gfx::Insets inset = GetInsets();
    597   text_border_->SetInsets(inset.top(), left, inset.bottom(), right);
    598   OnBoundsChanged(GetBounds());
    599 }
    600 
    601 void NativeTextfieldViews::UpdateVerticalMargins() {
    602   int top, bottom;
    603   if (!textfield_->GetVerticalMargins(&top, &bottom))
    604     return;
    605   gfx::Insets inset = GetInsets();
    606   text_border_->SetInsets(top, inset.left(), bottom, inset.right());
    607   OnBoundsChanged(GetBounds());
    608 }
    609 
    610 void NativeTextfieldViews::UpdateVerticalAlignment() {
    611   GetRenderText()->SetVerticalAlignment(textfield_->vertical_alignment());
    612   SchedulePaint();
    613 }
    614 
    615 bool NativeTextfieldViews::SetFocus() {
    616   return false;
    617 }
    618 
    619 View* NativeTextfieldViews::GetView() {
    620   return this;
    621 }
    622 
    623 gfx::NativeView NativeTextfieldViews::GetTestingHandle() const {
    624   NOTREACHED();
    625   return NULL;
    626 }
    627 
    628 bool NativeTextfieldViews::IsIMEComposing() const {
    629   return model_->HasCompositionText();
    630 }
    631 
    632 ui::Range NativeTextfieldViews::GetSelectedRange() const {
    633   return GetRenderText()->selection();
    634 }
    635 
    636 void NativeTextfieldViews::SelectRange(const ui::Range& range) {
    637   model_->SelectRange(range);
    638   OnCaretBoundsChanged();
    639   SchedulePaint();
    640   textfield_->NotifyAccessibilityEvent(
    641       ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
    642 }
    643 
    644 gfx::SelectionModel NativeTextfieldViews::GetSelectionModel() const {
    645   return GetRenderText()->selection_model();
    646 }
    647 
    648 void NativeTextfieldViews::SelectSelectionModel(
    649     const gfx::SelectionModel& sel) {
    650   model_->SelectSelectionModel(sel);
    651   OnCaretBoundsChanged();
    652   SchedulePaint();
    653 }
    654 
    655 size_t NativeTextfieldViews::GetCursorPosition() const {
    656   return model_->GetCursorPosition();
    657 }
    658 
    659 bool NativeTextfieldViews::GetCursorEnabled() const {
    660   return GetRenderText()->cursor_enabled();
    661 }
    662 
    663 void NativeTextfieldViews::SetCursorEnabled(bool enabled) {
    664   GetRenderText()->SetCursorEnabled(enabled);
    665 }
    666 
    667 bool NativeTextfieldViews::HandleKeyPressed(const ui::KeyEvent& e) {
    668   TextfieldController* controller = textfield_->GetController();
    669   bool handled = false;
    670   if (controller)
    671     handled = controller->HandleKeyEvent(textfield_, e);
    672   touch_selection_controller_.reset();
    673   return handled || HandleKeyEvent(e);
    674 }
    675 
    676 bool NativeTextfieldViews::HandleKeyReleased(const ui::KeyEvent& e) {
    677   return false;  // crbug.com/127520
    678 }
    679 
    680 void NativeTextfieldViews::HandleFocus() {
    681   GetRenderText()->set_focused(true);
    682   is_cursor_visible_ = true;
    683   SchedulePaint();
    684   GetInputMethod()->OnFocus();
    685   OnCaretBoundsChanged();
    686   // Start blinking cursor.
    687   base::MessageLoop::current()->PostDelayedTask(
    688       FROM_HERE,
    689       base::Bind(&NativeTextfieldViews::UpdateCursor,
    690                  cursor_timer_.GetWeakPtr()),
    691       base::TimeDelta::FromMilliseconds(kCursorBlinkCycleMs / 2));
    692 }
    693 
    694 void NativeTextfieldViews::HandleBlur() {
    695   GetRenderText()->set_focused(false);
    696   GetInputMethod()->OnBlur();
    697   // Stop blinking cursor.
    698   cursor_timer_.InvalidateWeakPtrs();
    699   if (is_cursor_visible_) {
    700     is_cursor_visible_ = false;
    701     RepaintCursor();
    702   }
    703 
    704   touch_selection_controller_.reset();
    705 
    706   ClearSelection();
    707 }
    708 
    709 ui::TextInputClient* NativeTextfieldViews::GetTextInputClient() {
    710   return textfield_->read_only() ? NULL : this;
    711 }
    712 
    713 void NativeTextfieldViews::ClearEditHistory() {
    714   model_->ClearEditHistory();
    715 }
    716 
    717 int NativeTextfieldViews::GetFontHeight() {
    718   return GetRenderText()->font_list().GetHeight();
    719 }
    720 
    721 int NativeTextfieldViews::GetTextfieldBaseline() const {
    722   return GetRenderText()->font_list().GetBaseline();
    723 }
    724 
    725 int NativeTextfieldViews::GetWidthNeededForText() const {
    726   return GetRenderText()->GetContentWidth() + GetInsets().width();
    727 }
    728 
    729 void NativeTextfieldViews::ExecuteTextCommand(int command_id) {
    730   ExecuteCommand(command_id, 0);
    731 }
    732 
    733 bool NativeTextfieldViews::HasTextBeingDragged() {
    734   return initiating_drag_;
    735 }
    736 
    737 /////////////////////////////////////////////////////////////////
    738 // NativeTextfieldViews, ui::SimpleMenuModel::Delegate overrides:
    739 
    740 bool NativeTextfieldViews::IsCommandIdChecked(int command_id) const {
    741   return true;
    742 }
    743 
    744 bool NativeTextfieldViews::IsCommandIdEnabled(int command_id) const {
    745   bool editable = !textfield_->read_only();
    746   string16 result;
    747   switch (command_id) {
    748     case IDS_APP_CUT:
    749       return editable && model_->HasSelection() && !textfield_->IsObscured();
    750     case IDS_APP_COPY:
    751       return model_->HasSelection() && !textfield_->IsObscured();
    752     case IDS_APP_PASTE:
    753       ui::Clipboard::GetForCurrentThread()->ReadText(
    754           ui::Clipboard::BUFFER_STANDARD, &result);
    755       return editable && !result.empty();
    756     case IDS_APP_DELETE:
    757       return editable && model_->HasSelection();
    758     case IDS_APP_SELECT_ALL:
    759       return !model_->GetText().empty();
    760     default:
    761       return textfield_->GetController()->IsCommandIdEnabled(command_id);
    762   }
    763 }
    764 
    765 bool NativeTextfieldViews::GetAcceleratorForCommandId(int command_id,
    766     ui::Accelerator* accelerator) {
    767   return false;
    768 }
    769 
    770 bool NativeTextfieldViews::IsItemForCommandIdDynamic(int command_id) const {
    771   const TextfieldController* controller = textfield_->GetController();
    772   return controller && controller->IsItemForCommandIdDynamic(command_id);
    773 }
    774 
    775 string16 NativeTextfieldViews::GetLabelForCommandId(int command_id) const {
    776   const TextfieldController* controller = textfield_->GetController();
    777   return controller ? controller->GetLabelForCommandId(command_id) : string16();
    778 }
    779 
    780 void NativeTextfieldViews::ExecuteCommand(int command_id, int event_flags) {
    781   touch_selection_controller_.reset();
    782   if (!IsCommandIdEnabled(command_id))
    783     return;
    784 
    785   TextfieldController* controller = textfield_->GetController();
    786   if (controller && controller->HandlesCommand(command_id)) {
    787     controller->ExecuteCommand(command_id, 0);
    788   } else {
    789     bool text_changed = false;
    790     switch (command_id) {
    791       case IDS_APP_CUT:
    792         OnBeforeUserAction();
    793         text_changed = Cut();
    794         UpdateAfterChange(text_changed, text_changed);
    795         OnAfterUserAction();
    796         break;
    797       case IDS_APP_COPY:
    798         OnBeforeUserAction();
    799         Copy();
    800         OnAfterUserAction();
    801         break;
    802       case IDS_APP_PASTE:
    803         OnBeforeUserAction();
    804         text_changed = Paste();
    805         UpdateAfterChange(text_changed, text_changed);
    806         OnAfterUserAction();
    807         break;
    808       case IDS_APP_DELETE:
    809         OnBeforeUserAction();
    810         text_changed = model_->Delete();
    811         UpdateAfterChange(text_changed, text_changed);
    812         OnAfterUserAction();
    813         break;
    814       case IDS_APP_SELECT_ALL:
    815         OnBeforeUserAction();
    816         SelectAll(false);
    817         UpdateAfterChange(false, true);
    818         OnAfterUserAction();
    819         break;
    820       default:
    821         controller->ExecuteCommand(command_id, 0);
    822         break;
    823     }
    824   }
    825 }
    826 
    827 void NativeTextfieldViews::SetColor(SkColor value) {
    828   GetRenderText()->SetColor(value);
    829   SchedulePaint();
    830 }
    831 
    832 void NativeTextfieldViews::ApplyColor(SkColor value, const ui::Range& range) {
    833   GetRenderText()->ApplyColor(value, range);
    834   SchedulePaint();
    835 }
    836 
    837 void NativeTextfieldViews::SetStyle(gfx::TextStyle style, bool value) {
    838   GetRenderText()->SetStyle(style, value);
    839   SchedulePaint();
    840 }
    841 
    842 void NativeTextfieldViews::ApplyStyle(gfx::TextStyle style,
    843                                       bool value,
    844                                       const ui::Range& range) {
    845   GetRenderText()->ApplyStyle(style, value, range);
    846   SchedulePaint();
    847 }
    848 
    849 void NativeTextfieldViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
    850   // Set the RenderText display area.
    851   gfx::Insets insets = GetInsets();
    852   gfx::Rect display_rect(insets.left(),
    853                          insets.top(),
    854                          width() - insets.width(),
    855                          height() - insets.height());
    856   GetRenderText()->SetDisplayRect(display_rect);
    857   OnCaretBoundsChanged();
    858 }
    859 
    860 ///////////////////////////////////////////////////////////////////////////////
    861 // NativeTextfieldViews, ui::TextInputClient implementation, private:
    862 
    863 void NativeTextfieldViews::SetCompositionText(
    864     const ui::CompositionText& composition) {
    865   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
    866     return;
    867 
    868   OnBeforeUserAction();
    869   skip_input_method_cancel_composition_ = true;
    870   model_->SetCompositionText(composition);
    871   skip_input_method_cancel_composition_ = false;
    872   UpdateAfterChange(true, true);
    873   OnAfterUserAction();
    874 }
    875 
    876 void NativeTextfieldViews::ConfirmCompositionText() {
    877   if (!model_->HasCompositionText())
    878     return;
    879 
    880   OnBeforeUserAction();
    881   skip_input_method_cancel_composition_ = true;
    882   model_->ConfirmCompositionText();
    883   skip_input_method_cancel_composition_ = false;
    884   UpdateAfterChange(true, true);
    885   OnAfterUserAction();
    886 }
    887 
    888 void NativeTextfieldViews::ClearCompositionText() {
    889   if (!model_->HasCompositionText())
    890     return;
    891 
    892   OnBeforeUserAction();
    893   skip_input_method_cancel_composition_ = true;
    894   model_->CancelCompositionText();
    895   skip_input_method_cancel_composition_ = false;
    896   UpdateAfterChange(true, true);
    897   OnAfterUserAction();
    898 }
    899 
    900 void NativeTextfieldViews::InsertText(const string16& text) {
    901   // TODO(suzhe): Filter invalid characters.
    902   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || text.empty())
    903     return;
    904 
    905   OnBeforeUserAction();
    906   skip_input_method_cancel_composition_ = true;
    907   if (GetRenderText()->insert_mode())
    908     model_->InsertText(GetTextForDisplay(text));
    909   else
    910     model_->ReplaceText(GetTextForDisplay(text));
    911   skip_input_method_cancel_composition_ = false;
    912   UpdateAfterChange(true, true);
    913   OnAfterUserAction();
    914 }
    915 
    916 void NativeTextfieldViews::InsertChar(char16 ch, int flags) {
    917   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE ||
    918       !ShouldInsertChar(ch, flags)) {
    919     return;
    920   }
    921 
    922   OnBeforeUserAction();
    923   skip_input_method_cancel_composition_ = true;
    924   if (GetRenderText()->insert_mode())
    925     model_->InsertChar(ch);
    926   else
    927     model_->ReplaceChar(ch);
    928   skip_input_method_cancel_composition_ = false;
    929 
    930   model_->SetText(GetTextForDisplay(GetText()));
    931 
    932   UpdateAfterChange(true, true);
    933   OnAfterUserAction();
    934 
    935   if (textfield_->IsObscured()) {
    936     const base::TimeDelta& reveal_duration =
    937         textfield_->obscured_reveal_duration();
    938     if (reveal_duration != base::TimeDelta()) {
    939       const size_t change_offset = model_->GetCursorPosition();
    940       DCHECK_GT(change_offset, 0u);
    941       RevealObscuredChar(change_offset - 1, reveal_duration);
    942     }
    943   }
    944 }
    945 
    946 gfx::NativeWindow NativeTextfieldViews::GetAttachedWindow() const {
    947   // Imagine the following hierarchy.
    948   //   [NativeWidget A] - FocusManager
    949   //     [View]
    950   //     [NativeWidget B]
    951   //       [View]
    952   //         [View X]
    953   // An important thing is that [NativeWidget A] owns Win32 input focus even
    954   // when [View X] is logically focused by FocusManager. As a result, an Win32
    955   // IME may want to interact with the native view of [NativeWidget A] rather
    956   // than that of [NativeWidget B]. This is why we need to call
    957   // GetTopLevelWidget() here.
    958   return GetWidget()->GetTopLevelWidget()->GetNativeView();
    959 }
    960 
    961 ui::TextInputType NativeTextfieldViews::GetTextInputType() const {
    962   return textfield_->GetTextInputType();
    963 }
    964 
    965 ui::TextInputMode NativeTextfieldViews::GetTextInputMode() const {
    966   return ui::TEXT_INPUT_MODE_DEFAULT;
    967 }
    968 
    969 bool NativeTextfieldViews::CanComposeInline() const {
    970   return true;
    971 }
    972 
    973 gfx::Rect NativeTextfieldViews::GetCaretBounds() {
    974   // TextInputClient::GetCaretBounds is expected to return a value in screen
    975   // coordinates.
    976   gfx::Rect rect = GetRenderText()->GetUpdatedCursorBounds();
    977   ConvertRectToScreen(this, &rect);
    978   return rect;
    979 }
    980 
    981 bool NativeTextfieldViews::GetCompositionCharacterBounds(uint32 index,
    982                                                          gfx::Rect* rect) {
    983   DCHECK(rect);
    984   if (!HasCompositionText())
    985     return false;
    986   const ui::Range& composition_range = GetRenderText()->GetCompositionRange();
    987   const uint32 left_cursor_pos = composition_range.start() + index;
    988   const uint32 right_cursor_pos = composition_range.start() + index + 1;
    989   DCHECK(!composition_range.is_empty());
    990   if (composition_range.end() < right_cursor_pos)
    991     return false;
    992   const gfx::SelectionModel start_position(left_cursor_pos,
    993                                            gfx::CURSOR_BACKWARD);
    994   const gfx::SelectionModel end_position(right_cursor_pos,
    995                                          gfx::CURSOR_BACKWARD);
    996   gfx::Rect start_cursor = GetRenderText()->GetCursorBounds(start_position,
    997                                                             false);
    998   gfx::Rect end_cursor = GetRenderText()->GetCursorBounds(end_position, false);
    999 
   1000   // TextInputClient::GetCompositionCharacterBounds is expected to fill |rect|
   1001   // in screen coordinates and GetCaretBounds returns screen coordinates.
   1002   *rect = gfx::Rect(start_cursor.x(),
   1003                     start_cursor.y(),
   1004                     end_cursor.x() - start_cursor.x(),
   1005                     start_cursor.height());
   1006   ConvertRectToScreen(this, rect);
   1007 
   1008   return true;
   1009 }
   1010 
   1011 bool NativeTextfieldViews::HasCompositionText() {
   1012   return model_->HasCompositionText();
   1013 }
   1014 
   1015 bool NativeTextfieldViews::GetTextRange(ui::Range* range) {
   1016   if (!ImeEditingAllowed())
   1017     return false;
   1018 
   1019   model_->GetTextRange(range);
   1020   return true;
   1021 }
   1022 
   1023 bool NativeTextfieldViews::GetCompositionTextRange(ui::Range* range) {
   1024   if (!ImeEditingAllowed())
   1025     return false;
   1026 
   1027   model_->GetCompositionTextRange(range);
   1028   return true;
   1029 }
   1030 
   1031 bool NativeTextfieldViews::GetSelectionRange(ui::Range* range) {
   1032   if (!ImeEditingAllowed())
   1033     return false;
   1034   *range = GetSelectedRange();
   1035   return true;
   1036 }
   1037 
   1038 bool NativeTextfieldViews::SetSelectionRange(const ui::Range& range) {
   1039   if (!ImeEditingAllowed() || !range.IsValid())
   1040     return false;
   1041 
   1042   OnBeforeUserAction();
   1043   SelectRange(range);
   1044   OnAfterUserAction();
   1045   return true;
   1046 }
   1047 
   1048 bool NativeTextfieldViews::DeleteRange(const ui::Range& range) {
   1049   if (!ImeEditingAllowed() || range.is_empty())
   1050     return false;
   1051 
   1052   OnBeforeUserAction();
   1053   model_->SelectRange(range);
   1054   if (model_->HasSelection()) {
   1055     model_->DeleteSelection();
   1056     UpdateAfterChange(true, true);
   1057   }
   1058   OnAfterUserAction();
   1059   return true;
   1060 }
   1061 
   1062 bool NativeTextfieldViews::GetTextFromRange(
   1063     const ui::Range& range,
   1064     string16* text) {
   1065   if (!ImeEditingAllowed() || !range.IsValid())
   1066     return false;
   1067 
   1068   ui::Range text_range;
   1069   if (!GetTextRange(&text_range) || !text_range.Contains(range))
   1070     return false;
   1071 
   1072   *text = model_->GetTextFromRange(range);
   1073   return true;
   1074 }
   1075 
   1076 void NativeTextfieldViews::OnInputMethodChanged() {
   1077   // TODO(msw): NOTIMPLEMENTED(); see http://crbug.com/140402
   1078 }
   1079 
   1080 bool NativeTextfieldViews::ChangeTextDirectionAndLayoutAlignment(
   1081     base::i18n::TextDirection direction) {
   1082   NOTIMPLEMENTED();
   1083   return false;
   1084 }
   1085 
   1086 void NativeTextfieldViews::ExtendSelectionAndDelete(
   1087     size_t before,
   1088     size_t after) {
   1089   ui::Range range = GetSelectedRange();
   1090   DCHECK_GE(range.start(), before);
   1091 
   1092   range.set_start(range.start() - before);
   1093   range.set_end(range.end() + after);
   1094   ui::Range text_range;
   1095   if (GetTextRange(&text_range) && text_range.Contains(range))
   1096     DeleteRange(range);
   1097 }
   1098 
   1099 void NativeTextfieldViews::EnsureCaretInRect(const gfx::Rect& rect) {
   1100 }
   1101 
   1102 void NativeTextfieldViews::OnCompositionTextConfirmedOrCleared() {
   1103   if (skip_input_method_cancel_composition_)
   1104     return;
   1105   DCHECK(textfield_->GetInputMethod());
   1106   textfield_->GetInputMethod()->CancelComposition(textfield_);
   1107 }
   1108 
   1109 gfx::RenderText* NativeTextfieldViews::GetRenderText() const {
   1110   return model_->render_text();
   1111 }
   1112 
   1113 string16 NativeTextfieldViews::GetTextForDisplay(const string16& text) {
   1114   return textfield_->style() & Textfield::STYLE_LOWERCASE ?
   1115       base::i18n::ToLower(text) : text;
   1116 }
   1117 
   1118 void NativeTextfieldViews::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
   1119   UpdateTextColor();
   1120   UpdateBackgroundColor();
   1121   gfx::RenderText* render_text = GetRenderText();
   1122   render_text->set_cursor_color(textfield_->GetTextColor());
   1123   render_text->set_selection_color(theme->GetSystemColor(
   1124       ui::NativeTheme::kColorId_TextfieldSelectionColor));
   1125   render_text->set_selection_background_focused_color(theme->GetSystemColor(
   1126       ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused));
   1127 }
   1128 
   1129 void NativeTextfieldViews::UpdateCursor() {
   1130   is_cursor_visible_ = !is_cursor_visible_;
   1131   RepaintCursor();
   1132   base::MessageLoop::current()->PostDelayedTask(
   1133       FROM_HERE,
   1134       base::Bind(&NativeTextfieldViews::UpdateCursor,
   1135                  cursor_timer_.GetWeakPtr()),
   1136       base::TimeDelta::FromMilliseconds(kCursorBlinkCycleMs / 2));
   1137 }
   1138 
   1139 void NativeTextfieldViews::RepaintCursor() {
   1140   gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds());
   1141   r.Inset(-1, -1, -1, -1);
   1142   SchedulePaintInRect(r);
   1143 }
   1144 
   1145 void NativeTextfieldViews::PaintTextAndCursor(gfx::Canvas* canvas) {
   1146   TRACE_EVENT0("views", "NativeTextfieldViews::PaintTextAndCursor");
   1147   canvas->Save();
   1148   GetRenderText()->set_cursor_visible(!is_drop_cursor_visible_ &&
   1149       is_cursor_visible_ && !model_->HasSelection());
   1150   // Draw the text, cursor, and selection.
   1151   GetRenderText()->Draw(canvas);
   1152 
   1153   // Draw the detached drop cursor that marks where the text will be dropped.
   1154   if (is_drop_cursor_visible_)
   1155     GetRenderText()->DrawCursor(canvas, drop_cursor_position_);
   1156 
   1157   // Draw placeholder text if needed.
   1158   if (model_->GetText().empty() &&
   1159       !textfield_->placeholder_text().empty()) {
   1160     canvas->DrawStringInt(
   1161         textfield_->placeholder_text(),
   1162         GetRenderText()->GetPrimaryFont(),
   1163         textfield_->placeholder_text_color(),
   1164         GetRenderText()->display_rect());
   1165   }
   1166   canvas->Restore();
   1167 }
   1168 
   1169 bool NativeTextfieldViews::HandleKeyEvent(const ui::KeyEvent& key_event) {
   1170   // TODO(oshima): Refactor and consolidate with ExecuteCommand.
   1171   if (key_event.type() == ui::ET_KEY_PRESSED) {
   1172     ui::KeyboardCode key_code = key_event.key_code();
   1173     if (key_code == ui::VKEY_TAB || key_event.IsUnicodeKeyCode())
   1174       return false;
   1175 
   1176     OnBeforeUserAction();
   1177     const bool editable = !textfield_->read_only();
   1178     const bool readable = !textfield_->IsObscured();
   1179     const bool shift = key_event.IsShiftDown();
   1180     const bool control = key_event.IsControlDown();
   1181     const bool alt = key_event.IsAltDown();
   1182     bool text_changed = false;
   1183     bool cursor_changed = false;
   1184     switch (key_code) {
   1185       case ui::VKEY_Z:
   1186         if (control && !shift && !alt && editable)
   1187           cursor_changed = text_changed = model_->Undo();
   1188         else if (control && shift && !alt && editable)
   1189           cursor_changed = text_changed = model_->Redo();
   1190         break;
   1191       case ui::VKEY_Y:
   1192         if (control && !alt && editable)
   1193           cursor_changed = text_changed = model_->Redo();
   1194         break;
   1195       case ui::VKEY_A:
   1196         if (control && !alt) {
   1197           model_->SelectAll(false);
   1198           cursor_changed = true;
   1199         }
   1200         break;
   1201       case ui::VKEY_X:
   1202         if (control && !alt && editable && readable)
   1203           cursor_changed = text_changed = Cut();
   1204         break;
   1205       case ui::VKEY_C:
   1206         if (control && !alt && readable)
   1207           Copy();
   1208         break;
   1209       case ui::VKEY_V:
   1210         if (control && !alt && editable)
   1211           cursor_changed = text_changed = Paste();
   1212         break;
   1213       case ui::VKEY_RIGHT:
   1214       case ui::VKEY_LEFT: {
   1215         // We should ignore the alt-left/right keys because alt key doesn't make
   1216         // any special effects for them and they can be shortcut keys such like
   1217         // forward/back of the browser history.
   1218         if (alt)
   1219           break;
   1220         const ui::Range selection_range = GetSelectedRange();
   1221         model_->MoveCursor(
   1222             control ? gfx::WORD_BREAK : gfx::CHARACTER_BREAK,
   1223             (key_code == ui::VKEY_RIGHT) ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT,
   1224             shift);
   1225         cursor_changed = GetSelectedRange() != selection_range;
   1226         break;
   1227       }
   1228       case ui::VKEY_END:
   1229       case ui::VKEY_HOME:
   1230         if ((key_code == ui::VKEY_HOME) ==
   1231             (GetRenderText()->GetTextDirection() == base::i18n::RIGHT_TO_LEFT))
   1232           model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, shift);
   1233         else
   1234           model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, shift);
   1235         cursor_changed = true;
   1236         break;
   1237       case ui::VKEY_BACK:
   1238       case ui::VKEY_DELETE:
   1239         if (!editable)
   1240           break;
   1241         if (!model_->HasSelection()) {
   1242           gfx::VisualCursorDirection direction = (key_code == ui::VKEY_DELETE) ?
   1243               gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
   1244           if (shift && control) {
   1245             // If both shift and control are pressed, then erase up to the
   1246             // beginning/end of the buffer in ChromeOS. In windows, do nothing.
   1247 #if defined(OS_WIN)
   1248             break;
   1249 #else
   1250             model_->MoveCursor(gfx::LINE_BREAK, direction, true);
   1251 #endif
   1252           } else if (control) {
   1253             // If only control is pressed, then erase the previous/next word.
   1254             model_->MoveCursor(gfx::WORD_BREAK, direction, true);
   1255           }
   1256         }
   1257         if (key_code == ui::VKEY_BACK)
   1258           model_->Backspace();
   1259         else if (shift && model_->HasSelection() && readable)
   1260           Cut();
   1261         else
   1262           model_->Delete();
   1263 
   1264         // Consume backspace and delete keys even if the edit did nothing. This
   1265         // prevents potential unintended side-effects of further event handling.
   1266         text_changed = true;
   1267         break;
   1268       case ui::VKEY_INSERT:
   1269         if (control && !shift && readable)
   1270           Copy();
   1271         else if (shift && !control && editable)
   1272           cursor_changed = text_changed = Paste();
   1273         break;
   1274       default:
   1275         break;
   1276     }
   1277 
   1278     // We must have input method in order to support text input.
   1279     DCHECK(textfield_->GetInputMethod());
   1280 
   1281     UpdateAfterChange(text_changed, cursor_changed);
   1282     OnAfterUserAction();
   1283     return (text_changed || cursor_changed);
   1284   }
   1285   return false;
   1286 }
   1287 
   1288 bool NativeTextfieldViews::MoveCursorTo(const gfx::Point& point, bool select) {
   1289   if (!model_->MoveCursorTo(point, select))
   1290     return false;
   1291   OnCaretBoundsChanged();
   1292   return true;
   1293 }
   1294 
   1295 void NativeTextfieldViews::PropagateTextChange() {
   1296   textfield_->SyncText();
   1297 }
   1298 
   1299 void NativeTextfieldViews::UpdateAfterChange(bool text_changed,
   1300                                              bool cursor_changed) {
   1301   if (text_changed) {
   1302     PropagateTextChange();
   1303     textfield_->NotifyAccessibilityEvent(
   1304         ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
   1305   }
   1306   if (cursor_changed) {
   1307     is_cursor_visible_ = true;
   1308     RepaintCursor();
   1309     if (!text_changed) {
   1310       // TEXT_CHANGED implies SELECTION_CHANGED, so we only need to fire
   1311       // this if only the selection changed.
   1312       textfield_->NotifyAccessibilityEvent(
   1313           ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
   1314     }
   1315   }
   1316   if (text_changed || cursor_changed) {
   1317     OnCaretBoundsChanged();
   1318     SchedulePaint();
   1319   }
   1320 }
   1321 
   1322 void NativeTextfieldViews::UpdateContextMenu() {
   1323   if (!context_menu_contents_.get()) {
   1324     context_menu_contents_.reset(new ui::SimpleMenuModel(this));
   1325     context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
   1326     context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
   1327     context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
   1328     context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE);
   1329     context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
   1330     context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
   1331                                                 IDS_APP_SELECT_ALL);
   1332     TextfieldController* controller = textfield_->GetController();
   1333     if (controller)
   1334       controller->UpdateContextMenu(context_menu_contents_.get());
   1335 
   1336     context_menu_delegate_.reset(
   1337         new views::MenuModelAdapter(context_menu_contents_.get()));
   1338     context_menu_runner_.reset(
   1339         new MenuRunner(new views::MenuItemView(context_menu_delegate_.get())));
   1340   }
   1341 
   1342   context_menu_delegate_->BuildMenu(context_menu_runner_->GetMenu());
   1343 }
   1344 
   1345 void NativeTextfieldViews::OnTextInputTypeChanged() {
   1346   // TODO(suzhe): changed from DCHECK. See http://crbug.com/81320.
   1347   if (textfield_->GetInputMethod())
   1348     textfield_->GetInputMethod()->OnTextInputTypeChanged(textfield_);
   1349 }
   1350 
   1351 void NativeTextfieldViews::OnCaretBoundsChanged() {
   1352   // TODO(suzhe): changed from DCHECK. See http://crbug.com/81320.
   1353   if (textfield_->GetInputMethod())
   1354     textfield_->GetInputMethod()->OnCaretBoundsChanged(textfield_);
   1355 
   1356   // Notify selection controller
   1357   if (touch_selection_controller_.get())
   1358     touch_selection_controller_->SelectionChanged();
   1359 }
   1360 
   1361 void NativeTextfieldViews::OnBeforeUserAction() {
   1362   TextfieldController* controller = textfield_->GetController();
   1363   if (controller)
   1364     controller->OnBeforeUserAction(textfield_);
   1365 }
   1366 
   1367 void NativeTextfieldViews::OnAfterUserAction() {
   1368   TextfieldController* controller = textfield_->GetController();
   1369   if (controller)
   1370     controller->OnAfterUserAction(textfield_);
   1371 }
   1372 
   1373 bool NativeTextfieldViews::Cut() {
   1374   if (!textfield_->read_only() && !textfield_->IsObscured() && model_->Cut()) {
   1375     TextfieldController* controller = textfield_->GetController();
   1376     if (controller)
   1377       controller->OnAfterCutOrCopy();
   1378     return true;
   1379   }
   1380   return false;
   1381 }
   1382 
   1383 bool NativeTextfieldViews::Copy() {
   1384   if (!textfield_->IsObscured() && model_->Copy()) {
   1385     TextfieldController* controller = textfield_->GetController();
   1386     if (controller)
   1387       controller->OnAfterCutOrCopy();
   1388     return true;
   1389   }
   1390   return false;
   1391 }
   1392 
   1393 bool NativeTextfieldViews::Paste() {
   1394   if (textfield_->read_only())
   1395     return false;
   1396 
   1397   const string16 original_text = GetText();
   1398   const bool success = model_->Paste();
   1399 
   1400   if (success) {
   1401     // As Paste is handled in model_->Paste(), the RenderText may contain
   1402     // upper case characters. This is not consistent with other places
   1403     // which keeps RenderText only containing lower case characters.
   1404     string16 new_text = GetTextForDisplay(GetText());
   1405     model_->SetText(new_text);
   1406 
   1407     TextfieldController* controller = textfield_->GetController();
   1408     if (controller)
   1409       controller->OnAfterPaste();
   1410   }
   1411   return success;
   1412 }
   1413 
   1414 void NativeTextfieldViews::TrackMouseClicks(const ui::MouseEvent& event) {
   1415   if (event.IsOnlyLeftMouseButton()) {
   1416     base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
   1417     if (time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
   1418         !ExceededDragThresholdFromLastClickLocation(event)) {
   1419       // Upon clicking after a triple click, the count should go back to double
   1420       // click and alternate between double and triple. This assignment maps
   1421       // 0 to 1, 1 to 2, 2 to 1.
   1422       aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
   1423     } else {
   1424       aggregated_clicks_ = 0;
   1425     }
   1426     last_click_time_ = event.time_stamp();
   1427     last_click_location_ = event.location();
   1428   }
   1429 }
   1430 
   1431 void NativeTextfieldViews::HandleMousePressEvent(const ui::MouseEvent& event) {
   1432   if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())
   1433     textfield_->RequestFocus();
   1434 
   1435   if (!event.IsOnlyLeftMouseButton())
   1436     return;
   1437 
   1438   initiating_drag_ = false;
   1439   bool can_drag = true;
   1440 
   1441   switch (aggregated_clicks_) {
   1442     case 0:
   1443       if (can_drag && GetRenderText()->IsPointInSelection(event.location()))
   1444         initiating_drag_ = true;
   1445       else
   1446         MoveCursorTo(event.location(), event.IsShiftDown());
   1447       break;
   1448     case 1:
   1449       MoveCursorTo(event.location(), false);
   1450       model_->SelectWord();
   1451       double_click_word_ = GetRenderText()->selection();
   1452       OnCaretBoundsChanged();
   1453       break;
   1454     case 2:
   1455       model_->SelectAll(false);
   1456       OnCaretBoundsChanged();
   1457       break;
   1458     default:
   1459       NOTREACHED();
   1460   }
   1461   SchedulePaint();
   1462 }
   1463 
   1464 bool NativeTextfieldViews::ImeEditingAllowed() const {
   1465   // We don't allow the input method to retrieve or delete content from a
   1466   // password field.
   1467   ui::TextInputType t = GetTextInputType();
   1468   return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD);
   1469 }
   1470 
   1471 // static
   1472 bool NativeTextfieldViews::ShouldInsertChar(char16 ch, int flags) {
   1473   // Filter out all control characters, including tab and new line characters,
   1474   // and all characters with Alt modifier. But we need to allow characters with
   1475   // AltGr modifier.
   1476   // On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a different
   1477   // flag that we don't care about.
   1478   return ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) &&
   1479       (flags & ~(ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN)) != ui::EF_ALT_DOWN;
   1480 }
   1481 
   1482 void NativeTextfieldViews::CreateTouchSelectionControllerAndNotifyIt() {
   1483   if (!touch_selection_controller_) {
   1484     touch_selection_controller_.reset(
   1485         ui::TouchSelectionController::create(this));
   1486   }
   1487   if (touch_selection_controller_)
   1488     touch_selection_controller_->SelectionChanged();
   1489 }
   1490 
   1491 void NativeTextfieldViews::PlatformGestureEventHandling(
   1492     const ui::GestureEvent* event) {
   1493 #if defined(OS_WIN) && defined(USE_AURA)
   1494   if (event->type() == ui::ET_GESTURE_TAP && !textfield_->read_only())
   1495     base::win::DisplayVirtualKeyboard();
   1496 #endif
   1497 }
   1498 
   1499 void NativeTextfieldViews::RevealObscuredChar(int index,
   1500                                               const base::TimeDelta& duration) {
   1501   GetRenderText()->SetObscuredRevealIndex(index);
   1502   SchedulePaint();
   1503 
   1504   if (index != -1) {
   1505     obscured_reveal_timer_.Start(
   1506         FROM_HERE,
   1507         duration,
   1508         base::Bind(&NativeTextfieldViews::RevealObscuredChar,
   1509                    base::Unretained(this), -1, base::TimeDelta()));
   1510   }
   1511 }
   1512 
   1513 }  // namespace views
   1514